#edu021. 第 2 节 数据类型与变量

第 2 节 数据类型与变量

变量就是存储数据的容器,其值可以改变,因此称为变量。

变量:先定义再使用

变量需要先定义再使用,定义变量的格式是

数据类型 变量名;

不同的数据类型,在内存中存储方式不同,C++ 中定义变量需要指明变量类型,接下来我们介绍 C++ 常用的数据类型。

一、标准数据类型

C++ 提供了丰富的数据类型 , 基本数据类型包括:整形(int,long long)、实型(double)、字符型(char)。

1.整型

常用的整数类型是:int ,long long,unsigned long long

利用 sizeof(int) 可以得到 int 占 4 个字节(Byte),又由于 1 Byte =8 bit ,那么 intint 类型变量在二进制下占 3232 位 (bit) 。对于带符号整型,最高位是符号位,符号位0代表正数,符号位1代表负数,那么 intint 类型变量能存储的最大正数就是:

$(\overbrace{0 \underbrace{11\cdots1}_{31位}}^{32位})_2=2^{30}+2^{29}+\cdots+2^0=2^{31}-1$

注:230+229++202^{30}+2^{29}+\cdots+2^0 可以利用等比数列前 nn 和公式 Sn=a1(1qn)1qS_n=\frac{a_1(1-q^n)}{1-q} , 首项 a1=20=1a_1=2^0=1 ,公比 q=2q=2 , Sn=2311S_n=2^{31}-1. 也可以利用二进制“逢二进一”,给 0111011\dots 111 ,再减 11

对于 $(\overbrace{{011\cdots11}}^{32位})_2+(\overbrace{{000\cdots01}}^{32位})_2=(\overbrace{{100\cdots00}}^{32位})_2=2^{31}$ , 那么 (0111132)2=2311(\overbrace{{011\cdots11}}^{32位})_2=2^{31}-1

通过计算 intint 类型变量能够存储的最大正整数就是 2311=21474836472^{31}-1=2147483647 ,下表列举了各种类型变量占用的字节数和存储范围。

数据类型 标识符 占字节数 数值范围
短整型 short [int] 2(16位) -32768~32767 2152151-2^{15}~2^{15}-1
整型 [long] int 4(32位) -2147483648~2147483647 2312311-2^{31}~2^{31}-1
长整型 long [int]
超长整型 long long [int] 8(64位) -9223372036854775808~9223372036854775807 2632631-2^{63}~2^{63}-1
无符号整型 unsigned int 4(32位) 0~4294967295 023210~2^{32}-1
无符号超长整型 unsigned long long 8(8位) 0~18446744073709551615 026410~2^{64}-1

【上机实验】:利用 cout<<sizeof(long long); 验证各种类型所占字节数。

2. 实型

实型在 C++ 中可以通过两种方式表示:

  • 小数形式:如 0.1, 15.51 等,这是最直观的表示方式。
  • 科学计数法:如 3.25E2 表示 3.25×1023.25×102 ,其中E或小写e表示指数部分,后面的数字必须为整数。

C++ 中的实型主要用于表示实数,通常分为两种类型:浮点型(float)和双精度型(double)。这两种实型的主要区别在于它们的存储空间和表示范围。

实型的分类

(1) 浮点型(float):占用 4 个字节(32位)。表示范围大约在 3.4×1038-3.4×10^{38}3.4×10383.4×10^{38} , 有效位数只有 6~7 位,通常用于需要较小精度的场合。

(2) 双精度型(double):占用 8 个字节(64位)。表示范围大约在 1.7×10308-1.7×10^{308}1.7×103081.7×10^{308} ,有效位数 15~16 位,提供更高的精度,信息竞赛如果使用实型,使用 double 类型或 long double 类型

实型数取值范围:

数据类型 标识符 占字节数 数值范围 有效位数
单精度实型 float 4(32位) -3.4E-38~3.4E+38 6~7位
双精度实型 double 8(64位) -1.7E+308~1.7E+308 15~16位
长双精度实型 long double 16(128位) -3.4E+4932~1.1E+4932 18~19位

【二进制表示的局限性】

在计算机中,实数使用二进制存储,这导致了大部分实数的存储不精确。例如十进制小数 0.10.1 转换为二进制小数后,是一个无限循环小数。

(0.1)10=(0.00˙011˙)2(0.1)_{10}=(0.0\dot{0}01\dot{1})_2

0.10.1 外,0.2,0.3,0.4,0.6,0.7,0.8,0.90.2,0.3,0.4,0.6,0.7,0.8,0.9 转化为二进制之后都将无限循环小数,只有特殊的小数二进制才能精确表示。 由于计算机的存储空间有限,必须舍弃多余的位数,从而导致精度损失。

3. 布尔类型(bool)

bool 类型是一种基本数据类型,用于表示逻辑值。

bool 类型占用 11 个字节(88 位)内存空间, 取值只能是 truefalse。关系表达式和逻辑表达式的值就是 bool 类型。

true 转化为数值就是 1 ,false 转化为数值就是 0 。反之,任何非零整数都可以被视为 true,而零则被视为false

4. 字符类型(char)

C++中的字符型(char)是一种基本数据类型,用于存储单个字符 , 占用 11 个字节(Byte) 的存储空间 ,可以存储 ASCII码表 中的所有字符,包括英文字母、数字和一些控制字符。

字符常量有以下两种表示法:

(1) 普通表示形式

字符常量是由单个字符组成,所有字符采用 ASCII 编码。在程序中,通常用一对单引号将单个字符括起来表示一个字符常量。如:'a','A','0' 等。如字符 'A' 的序号是 65,字符 'a' 的序号是 97, 字符 '0' 的序号的 48 。

ASCII编码表

ASCII编码表

【思考】大写与小写字母,在 ASCII 编码表中有何差异?

(2) 转义字符表示形式。

转义字符有三种用法:表示控制字符、表示特殊字符、表示所有字符。常用的转义字符如下表所示。

转义字符 含义 ASCII值
'\n' 换行 10
'\0' 空字符,字符串结束特殊标志 0
'\t' 水平制表 9
'\b' 退格 8
'\r' 回车(不换行),将当前位置移动到本行开头 13
'\’' 单引号 39
'\”' 双引号 34
'\ \ ' 一个反斜杠字符 92
'\ddd' 1~3位八进制数所代表的字符
'\xhh' 1~2位十六进制数所代表的字符

二、类型转换规则

C++语言中,不同数据类型的运算对象进行混合运算,或者需要将一个表达式的结果转换成期望的类型时,就需要依据数据类型转换规则进行转换。

1、混合运算时的类型转换规则

整型、实型、字符型数据间可以混合运算。在这种情况下,需要将不一致的数据类型转换成一致的数据类型,然后进行运算。为了保证运算精度,系统在运算时的转换规则是将存储长度较短的运算对象转成存储长度较长的类型,然后再进行处理。这种转换是系统自动进行的,如下图:

混合运算时的类型转换规则

混合运算时的类型转换规则

【说明】

  • (1) 纵向箭头表示必定会进行的转换,如 float 型数据必先转换为double型数据,然后与其他操作数进行运算。与此类似,char型 或 short型 数据必先转换为 int 型数据,然后进行运算。

  • (2) 横向箭头表示当运算对象为不同类型数据时的转换方向,如 int 型数据与 unsigned 型数据进行运算,int型转换为 unsigned型后方可进行运算。int 型与 double 型进行运算,int 型直接转换为 double 型后进行运算,不能理解为先转换为 unsigned int 型,然后转换为 long int 型,最后再转换为double型。

2、赋值时的类型转换规则

当赋值运算符两侧的数据类型不同时,需进行类型转换,这种转换是系统自动进行的,转换规则如下:

1)float、double 型赋值给 int 型:直接截断小数。

例如,int i=f+0.6;,f 的值为 4.0,右边算术表达式运算后的结果为 4.6 的 double 型数据,根据上述转换原则,直接舍弃小数,所以 i 的值为 4。

2) int、char 型赋值给 float、double 型:补足有效位以进行数据类型转换。

例如:float f=4;,float 为 7 位有效数字,所以 f 的值为 4.0000000。

3)char 型(1字节)赋给 int 型(4字节):数值赋给 int 型的低 8 位,其它位补 0 。

4)long long 型赋值给 int 型:long long 型截断低字节给 int 型。

5)int 型赋值给 long long 型:符号位单独赋值,将 int 数值位,赋给 long long,即保留 int 的符号和值。

6)unsigned int 型赋值给 int 型:直接传送数值。

7)非 unsigned int 型赋值给位数相同的 unsigned int 型:直接传送数值。

3、强制类型转换

在 C++ 语言中,还允许强制类型转换,即将某一数据的数据类型转换为指定的另一种数据类型,强制类型转换只是临时转换

强制转换运算符组成的运算表达式的一般形式为:

 (类型名)(表达式)

例如:已知有变量定义 int b=7;float a=2.5,c=4.7; ,求下面算术表达式的值。

a+(int)(b/3*(int)(a+c)/2.0)%4

根据运算符的结合性规则,表达式要自左至右执行,b/3为 2 ,2*(int)(a+c) 为 14,14/2.0 为 7.0,强制类型转换后为 7,7%4 为 3,a 的值 2.5 与 3 相加,最终结果为 5.5。

三、标识符命名规则

用一个合法的标识符代表一个变量。如 n,m,rot,total 等都是合法变量名。在程序中用到的变量要“先定义后使用”,变量名应遵循自定义标识符的命名规则,并建议使用“见名知义”的原则,即用一些有意义的单词作为变量名。在C++语言,变量名大小写有区别

用来标识变量名、符号常量名、函数名、数组名、类型名、文件名的有效字符序列称为标识符。

C++语言规定,标识符只能由字母(包含下划线“_”)开头,后面的字符可以是字母或数字。

对于标识符的长度,不同的C++语言编译器有不同的规定,考虑到系统的可移植性,建议变量名的长度不要超过8个字符。 例如: month、_age、s2 为合法的标识符; m.k.jack、a<=b、9y 为不合法的标识符。

【注意】:由于使用 <bits/stdc++.h> 全局标识符名很容易冲突,例如全局变量名冲突涉及到 j0 j1 jn y0 y1 yn,Windows 由于库不标准,Linux 系统下就会报错。

4、常量

与变量对应的值不能改变的量,就是常量。

常量是指在程序中使用的一些具体的数、字符。在程序运行过程中,其值不能被更改。

如 123, 145.88, 'm', true 等。

1、整型常量:如 3、-5、0 等。

整型常量是表示整数的常量。有三种表示形式:

1)十进制形式。如 99、-1。

2)八进制形式。以数字 0 打头,由 0-7 构成,如012,表示八进制整数 12,即 12(8)12_{(8)}

3)十六进制形式。以0x打头,如0x12A,表示十六进制整数 12A,即 12A(16)12A_{(16)}

2、实型常量:如 3.1、-6.1e+2(科学记数法)。

其中 -6.1e+2 是 double 类型的实数,值为 6.2×102-6.2\times 10^2 .

3、字符常量:是用单引号括起来的字符,如 'k' 、'5' 、'%'。

注意:'a' 与 "a" 表示的含义是不同的,'a' 表示一个字符常量,"a" 表示一个字符串。

符号常量

一个常量可以直接调用(如 124,'A' ),也可以给常量取个名字用一个标识符代表它,这就是符号常量。其语法格式为:

 const  符号常量=常量字串;

例如:const double PI=3.1415926;

也可以使用宏命令。例如

#define  PI  3.1415926

不过这种方式,只是编译前的替换

#define Pi 3+0.14
double r=10;
double area= 2*Pi*r

其中 2*Pi*r 编译前替换,就是 2*3+0.14*10 , 并不会自动添加括号。