2.1基本内置类型
零.前言
思来想去,由于书的排版本身就有很深的结构,而且单章跨度太大,不好写在一个博客里,所以干脆把一章里的5——8个小节分开写,单独成一篇文章。绝对不是什么水博客积分欢迎关注啊,毕竟会把一本近1000页的“圣经”浓缩成几十篇小博客QAQ
然后以后的博客命名方式会如下:
外部标题:【C++学习记录】—— 【我的第几篇文章】【书内大章标题】【章内小节标题】
内部标题: 第几章.第几小节 章内小节标题
---------------分----------界----------线------------------------------------------
这是前言的内容:
C++定义了一套包括算数类型和空类型在内的基本数据结构。
算数类型
包括:字符、整形数、布尔值和浮点数。
空类型
不对应具体的值,用于一些特殊的场合,比如函数无返回时,用空类型作为返回类型。
一.算数类型
算数类型分两类:整型(包括布尔和字符)
和浮点型
1.算数类型
算数类型的尺寸是由编译器决定的!!! 记住这句话,要考的!int的长度不是固定的4字节!
但一般来说,一个char的大小和一个机器字节一样的。且在C+++又有规定:
- 一个int至少和一个short一样大
- 一个long至少和一个int一样大
- 一个long long 至少和一个long一样大。
换句话说一个long long 所占的大小,至少是long int的2倍。
2.浮点型
浮点型可以表示单精度、双精度和拓展精度值。(但好像拓展精度值不常见啊!)
一般来说,类型float
和double
分别有7和16个有效位
3.带符号类型和无符号类型
除去布尔类型和拓展的字符型,其他的整形都可以划分为带符号的
和无符号的
。带符号的包含 正负数和零,而不带符号的只有正数和零。
我们可以通过添加关键字unsigned
到类型名前,就可以得到无符号类型的。
所以,我们的signed char
可以表示0<= X <= 255的值,而unsigned char
理论上可以表示成 -127<= X <= 127的值,但是现在绝大多数计算机会把它定义成 -128 <= X <= 127的值 。
注意:
- 不要在算数表达式里使用
char
或bool
,最好只在存放字符或者布尔值的时候使用。因为对于字符型来说它只有signed char
和unsigned char
两种类型,char
这个类型会由编译器来决定是那种类型 - 最好在浮点运算的时候选用
double
,因为单精度通常精度不够且双精度和单精度的浮点运算代价相差无几。(搞嵌入式或者对于空间使用量有要求的除外)。
二.类型转换
1.类型转换
遵从以下准则:0假1真
、浮点去尾
、整数添0
、无符号取余
- 非布尔 赋给 布尔类型,0变false,1变true
- 布尔类型 赋给 非布尔,false变0,true变1
- 浮点变为整数,只取整数部分
- 整数变浮点,小数直接全为0。如果该整型超过了浮点数的容量时,精度可能会丢失。
- 如果给一个无符号类型一个超过其范围的值时,结果是初始值对该无符号类型的最大值取模的余数(就是 %),比如我们把 -1 给 8bit的
unsigned char
,结果是 -1 ÷ 256 = 0 ··· 255(小学除法,大概吧), 这个结果就是255。 - 给符号类型一个超过其范围的值,结果是未定义的,此时,程序可能
继续工作
、崩溃
、生成垃圾数据
因为char的不确定性,所以建议大家在int和char进行运算的时候,还是吧char变成int比较好
所以,我们要避免无法预知和依赖于实现环境的行为,否则,这个程序移植起来,万一两个编译器不兼容,那这个查错是真的麻烦。
2.含有无符号类型的表达式
假设一个运算表达式里同时包含 有符号类型和无符号类型的值时, 有符号会转换成无符号类型的值
经典操作就是用无符号数去参与for循环,比如我自己犯过的错
unsigned int i;
for (i = 10; i >= 0; i--)
{}
这玩意儿是个死循环。
三.字面值常量
1.定义
一个形如42的值叫做字面值常量
,所以-42
不是字面值常量, 42是,而-
只是对该常量取负值而已。
2.整形和浮点类型字面值
我们常见的整型字面值可以用 8、10、16进制数表示。以0开头的是8进制,0x或0X开头是十六进制,那剩下的都当10进制处理。
比如8,10,16进制下的20(10), 024
、20
、0x14
。
默认情况下,十进制的字面值是带负号的类型中最小的类型,而8、16的类型是能容纳其数值类型的最小值。算了整一个表:
进制 | 范围 |
---|---|
十进制 | int 、long 、long long |
八、十六进制 | int 、unsigned int 、long 、unsigned long 、long long 、unsigned long long |
short
没有对应的字面值QAQ
3.字符合字符串字面值
‘a’字符字面值
“hello kanna” 字符串字面值
然而,字符串字面值是字符字面值构成的数组,而且编译器会在每个字符串的结尾添加一个空字符(’\0’),所以其实际长度比其表面长度多1.
所以最大长度为300的字符串我喜欢写301
以下是多行书写字符串字面值得方法
std::out << "can you can a can as a canner "
"can can a can?" << std::endl;
4.转义序列
其包含两类,一类是不可打印的字符,一类是特殊含义的字符,需要转义序列,包括
符号 | 含义 |
---|---|
\n | 换行符 |
\t | 横向制表符 |
\a | 报警符 |
\v | 纵向制表符 |
\b | 退格符 |
" | 单引号 |
\\ | 反斜线 |
\? | 问号 |
\’ | 单引号 |
\r | 回车符 |
\f | 进纸符 |
或者用泛化转义序列:
\7 响铃 \40 空格 \115 字符M \x4d 字符M
\后面紧跟1 2 3个八进制数字,\x跟一个或多个十六进制数字
注意:"\1234" 会输出 S4 而"\x1234"表示一个16位的字符
5.指定字面值的类型
我们可以通过添加前缀后缀,改变整型、浮点型和字符型字面值的默认类型,比如
L’a’ 、 u8"hi!"、1E-3F、3.14159L
放个表:
前缀 | 含义 | 类型 |
---|---|---|
u | unicode16字符 | char16_t |
U | unicode32字符 | char32_t |
L | 宽字符 | wchar_t |
u8 | UTF-8(仅用于字符串字面常量) | char |
后缀 | 最小匹配类型 |
---|---|
u or U | unsigned |
l or L | long |
ll or LL | long long |
后缀 | 类型 |
---|---|
f or F | float |
l或L | long double |
6. 布尔字面值和指针字面值
true
和 false
是布尔类型字面值:
bool test = false;
nullptr
是指针字面值,后面会提到