2.1 基本内置类型
文章目录
C++定义的基本内置类型可以分为以下2大类:
(1)算术类型。算术类型包括了字符、整型数、布尔值和浮点数。
(2)空类型。空类型不对应具体的值,仅用于一些特殊的场合,例如最常见的是,当函数不返回任何值时使用空类型作为返回值。
2.1.1 算术类型
算术类型可以分为2类:**整型(包括字符和布尔类型在内)**和 浮点型。
C语言支持整数和浮点数的多种数据格式。另外,C语言还提供了几种字符类型,其中多数支持国际化,基本的字符类型是char,一个char的空间应确保可以存放机器基本字符中任意字符对应的数字值,即,一个char的大小和一个机器字节一样。
基本C数据类型的32位和64位程序的典型大小(以字节为单位)如下:
类型 | 含义 | 32位下 | 64位下 |
---|---|---|---|
int | 基本整型 | 4字节(32位) | 4字节(32位) |
short | 短整型 | 2字节(16位) | 2字节(16位) |
long | 长整型 | 4字节(32位) | 4字节(32位) |
long long | 双长整型 | 8字节(64位) | 8字节(64位) |
char | 字符型 | 1字节(8位) | 1字节(8位) |
float | 单精度浮点型 | 4字节(32位) | 4字节(32位) |
double | 双精度浮点型 | 8字节(64位) | 8字节(64位) |
long double | 长双精型 | ? | ? |
char* | 指针 | ? | 4字节(32位) |
【带符号类型和无符号类型】
除去 布尔型和扩展的字符型外,其它整型可以划分为2种 :
(1)带符号的(signed) :带符号类型可以表示正数、负数或0。c++标准没有规定带符号类型应如何表示,但
是约定了在表示范围内正值和负值的量应该平衡。因此8比特的signed char理论上应该可以表示-127至127区
间内的值,大多数现代计算机将实际的表示范围定为-128至127。
【推导 signed char 的取值范围】
最小值: ( 10000000 ) 2 (10000000)_2 (10000000)2,第一位是1,表示其为负数,其表示的值的绝对值即为其补码,也就是对各位
取反后加1,因此为-128;
最大值: ( 01111111 ) 2 (01111111)_2 (01111111)2,也就是127.
(2)无符号的(unsigned) :无符号类型仅能表示大于等于0的数,它的所有比特都用来存储值。例如,8比特
的 unsigned char 可以表示为 0 至 255 区间内的值。
类型 int、short、long 和 long long 都是带符号的,通过在这些类型名前添加 unsigned 就可以得到其对应的无符号类型,例如 unsigned long。类型 unsigned int 可以缩写为 unsigned。
与其他整型不同,字符型被分为3种:char、signed char 和 unsigned char,其中类型char和类型signed char是不一样的。尽管字符型有3种,但字符的表现类型却只有带符号的和无符号的这2种,类型char实际上会表现为上述2种形式中的一种,具体是哪种由编译器决定。
2.1.2 类型转换
对象的类型定义了对象包含的数据和所能参与的运算。类型转换就是将一种给定的类型转换成另一种相关类型。
当把一种算术类型的值赋给另外一种类型时:
bool b = 42; // b为真
int i = b; // i的值为1
i = 3.14; // i的值为3
double pi = i; // pi的值为3.0
【无符号类型和有符号类型的类型转换】
先看下面这个例子:
unsigned char c = -1; // 假设char占8比特,c的值为255
signed char c2 = 256; // 假设char占8比特,c2的值是未定义的
在上述过程中可以看到:
(1)当赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。例如,8比特大小的 unsigned char 可以表示 0 到 255 区间的值,如果将一个区间外的值赋给它,则实际的结果是该值对256取模后的余数。正如上例中,当把 -1 赋给 c 时,就是将-1对256取模,即得到255.
(2)当赋给带符号类型一个超出它表示范围的值时,结果是未定义的。此时,程序可能继续工作、可能崩溃,也可能生成垃圾数据。
【含有无符号类型的表达式】
注意:如果表达式中既有带符号类型又有无符号类型,带符号数会自动转换成无符号数。
例如,当一个算术表达式里既有无符号数又有 int 值时,int值会自动转换成无符号数,这个过程等价于把int值直接赋给无符号变量:
unsigned u = 0;
int i = -42;
cout << i + i << endl; //输出-84
cout << u + i << endl; //此处先将i转换成unsigned,如果int占32位,则输出4294967254
当从一个无符号数中减去一个值时,不管该值是否为无符号数,都要确保结果不能是个负值,例如:
unsigned u1 = 42, u2 = 10;
cout << u1 - u2 << endl; //正确:输出为32
cout << u2 - u1 << endl; //正确:但是,结果为取模后的值,即4294967264,而不是-32
再如,下面这个是个死循环:
unsigned int k;
for(k = 10; k >=0; k--) {
cout << k << endl;
}
2.1.3 字面值常量
【整型的字面值常量】
【进制】
整型的字面值可以写作 十进制数、八进制数(以0开头)或十六进制数(以0x开头) 的形式,例如:
20 /*十进制*/ 024 /*八进制*/ 0x14 /*十六进制*/
【数据类型】
整型字面值的数据类型由它的值和符号决定。默认情况下:
(1)十进制字面值是带符号数,它的类型是 int、long、和 long long 中能容纳下当前字面值的尺寸最小的那个。
(2) 八进制和十六进制字面值既可能是带符号的也可能是无符号的,它的类型是能容纳下其数值的 int、unsigned int、long、unsigned long、long long 和 unsigned long 中尺寸最小的。
[注意】类型 short 没有对应的字面值。
【浮点型的字面值常量】
浮点型字面值表现为一个小数或以科学计数法表示的指数,其中指数部分用 E 或 e 标识:
3.14159 3.14159E0 0. 0e0 .001
默认的,浮点型字面值是一个 double。
【转义序列】
转义序列中,主要关注的是泛化的转义序列:
(1)\x 后紧跟 1 个或多个十六进制数字,其中数字部分表示的是字符对应的数值,例如 \x4d(字符M)。
(2)\ 后紧跟 1 个、2 个或 3 个八进制数,其中数字部分表示的是字符对应的数值,例如 \7(响铃)。
【注意】如果反斜线 \ 后紧跟着的八进制数字超过 3 个,那只有前 3 个数字与 \ 构成转义序列,例如,“\1234"表示 2 个字符,即八进制数 123 对应的字符以及字符 4. 相反,\x 要用到后面跟着的所有数字,例如 “\x1234”表示一个16位的字符,该字符由 4 个十六进制数所对应的比特唯一确定。
【指定字面值的类型】
1. 字符和字符串字面值
前缀 含义 类型
u Unicode 16字符 char16_t
U Unicode 32字符 char32_t
L 宽字符 wchar_t
u8 UTF-8(仅用于字符串字面常量) char
2. 整型字面值
后缀 最小匹配类型
u or U unsigned
l or L long
ll or LL long long
3. 浮点型字面值
后缀 类型
f or F float
l or L long double
通过添加如上表所列出的前缀和后缀,可以改变整型、浮点型和字符型字面值的默认类型。例如:
L'a' // 宽字符型字面值,类型是wchar_t
u8"hi!" // utf-8字符串字面值(utf-8用8位编码一个Unicode字符)
42ULL // 无符号整型字面值,类型是unsigned long long
1E-3F // 单精度浮点型字面值,类型是float
3.14159L // 扩展精度浮点型字面值,类型是long double