C++基本内置类型
(博文参考书籍《C++ Primer 中文版》,摘录易忘知识点和容易混淆的内容)
C++定义了一套包括算术类型(arithmetic type)和空类型(void)在内的基本数据类型。
其中算术类型包含:字符、整数型、布尔值、浮点数。
空类型不对应具体的值,仅用于一些特定场合,常见的如:函数不返回任何值是,使用空类型作为函数的返回类型。
一、算术类型
算术类型分为两类:整形(intergral type,包括字符和布尔类型在内)、浮点型。
算术类型的尺寸(也就是该类型数据所占的比特数)在不同机器上有所差别。下方列出了C++标准规定的尺寸的最小值,同时允许编译器赋予这些类型更大的尺寸。某一类型所占的比特数不同,他所能表示的数据范围也不一样。
类型 |
含义 | 最小尺寸 | 数据范围 |
bool | 布尔类型 | 未定义 | |
char | 字符 | 8位 |
带符号:signed char -128 ~127 无符号:unsiged char 0~255 |
wchar_t | 宽字符 | 16位 | |
char16_t | Unicode字符 | 16位 | |
char32_t | Unicode字符 | 32位 | |
short | 短整型 | 16位 | -2的8次方 ~ 2的8次方-1 |
int | 整型 | 16位 | -2的8次方 ~ 2的8次方-1 |
long | 长整型 | 32位 | -2的16次方 ~ 2的16次方-1 |
long long | 长整型 | 64位 | -2的32次方 ~ 2的32次方-1 |
float | 单精度浮点型 | 6位有效数字 | |
double | 双精度浮点型 | 10位有效数字 | |
long double | 扩展精度浮点型 | 10位有效数字 |
布尔类型的取值是真(true)或假(false)。
基本的字符类型是char,一个char的空间应确保可以存放机器基本字符集中任意字符对应的数字值。也就是说,一个char的大小和一个机器字节一样。
内置类型的机器实现
计算机以比特序列存储数据,每个比特非0即1。
大多数的计算机以2的整数次幂个比特作为块来处理内存,可寻址的最小内存块成为“字节(byte)”,存储的基本单元称为“字(word)”,它通常由几个字节组成。C++语言中,一个字节要至少能容纳机器基本字符集中的字符。大多数机器的字节由8比特构成,字则由32或64比特构成,也就是4或8字节。
大多数计算机将内存中的每个字节与一个数字(被称为“地址(address)”)关联起来,在一个字节位8比特、字为32比特的机器上,我们可能看到一个字的内存区域如下所示
地址 | 内容 |
736424 | 1 0 0 1 0 1 1 0 |
736425 | 0 0 1 1 0 1 0 1 |
736426 | 0 1 0 1 0 0 1 1 |
736427 | 0 1 1 0 0 1 0 0 |
我们能够使用地址来表述这个地址开始的大小不同的比特串,为了赋予内存中某个地址明确的含义,必须首先知道存储在该地址的数据的类型。类型决定了数据所占的比特数以及该如何解释这些比特的内容。
带符号类型和无符号类型
除去布尔型和扩展的字符型之外,其他整型可以划分为带符号的(signed)和无符号的(unsigned)两种。类型int、short、long 和long long都是带符号的,通过在这些类型名前添加unsigned即可得到无符号类型。类型 unsigned int 可以缩写为 unsigned.
与其他整型不同,字符型被分为了三种:char、 singed char 和unsigned char。特别需要注意的是:类型char 和类型 signed char并不一样。尽管字符型有三种,但是字符的表现形式却只有两种,带符号的和无符号的。类型char 实际上会表现为上述两种形式中的一种,具体是哪种由编译器决定。
二、自动类型转换
1、非布尔型 --> 布尔型:初始值为0则为false,否则为true
2、布尔型 --> 非布尔型:true --> 1; false --> 0
3、整数值 --> 浮点型:小数部分记为0
4、负值 --> 无符号型:结果为初始值对无符号类型表示数值总数取模后的余数。列如:unsigned char 可以表示0~255,我们给个-1,就是对256取模,得到余数255.
这里我们来看一个代码示例:通过控制变量递减的方式把10到0的数字降序输出
#include <iostream> using namespace std; //倒序输出10-0 void DescPrintTenToOne() { cout << "带符号的" << endl; for (int i = 10;i >= 0; i--)//正确,如我们预取的效果一样 { cout << i << endl; } cout << "无符号的" << endl; for (unsigned j = 10; j >= 0; j--) //由于负值向无符号转换,进入了死循环 { cout << j << endl; } } int main() { DescPrintTenToOne(); return 0; }
下面我们看一下控制台的打印效果
5、当我们给带符号类型一个超出它表示范围的值时,结果是未定义的(undefined)。此时,程序可能继续工作、可能崩溃、也可能生成垃圾数据