计算机内存的基本单位是位(bit),字节(byte)通常指的是8位的内存单元,从这个意义上来说,字节指的就是描述计算机内存量的度量单位。
C++对字节的定义则有些不同,C++字节由至少能够容纳实现的基本字符集的相邻位组成,也就是说,可能取值的数目必须等于或超过字符数目。最开始的基本字符集ASCII由于只支持拉丁字符,可以用8位来容纳,因此ASCII编码是1个字节表示一个字符。但是在国际编程可能需要使用更大的字符集,即Unicode,根据编码方式可以分为UTF-8(变长编码,使用1-4个字节表示一个字符)、UTF-16(变长编码,使用2或4个字节表示一个字符)、UTF-32(定长编码,使用4个字节表示一个字符)。
英文字符和汉字字符在UTF-8编码环境下,测试结果如下:
#include
#include
using namespace std;
int main()
{
char a = 'a';
cout << a << endl; // 输出:a
// 1、‘中’字符超出了char单个字节的存储范围
char b = '中'; // 编译告警: overflow in conversion from 'int' to 'char' changes value from '14989485' to ''\37777777655'' [-Woverflow]
cout << b << endl; // 输出:乱码
// 2、‘中’字符在UTF-8编码中占用字节数为3,char数组定义为4是为了在末位存储结束符‘\0’
// char bs1[2] = "中"; //编译报错:error: initializer-string for array of chars is too long [-fpermissive]
char bs2[4] = "中";
cout << bs2 << endl; // 输出:中
cout << strlen("中") << endl; // 输出:3
return 0;
}
常用的整数类型有char、short、int、long、long long,根据是否能存储负值,又可以进一步划分为有符号整型和无符号整型。
由于系统环境或编译器环境不同,每种整型所占的字节数可能会有差异,此处以64位编译器为例,举例说明整型的取值范围:
类型 | 占用字节数 | 取值范围 |
---|---|---|
signed char | 1 | -2^7 ~ 2^7-1 |
unsigned char | 1 | 0 ~ 2^8-1 |
short | 2 | -2^15 ~ 2^15-1 |
unsigned short | 2 | 0 ~ 2^16-1 |
int | 4 | -2^31 ~ 2^31-1 |
unsigned int | 4 | 0 ~ 2^32-1 |
long | 4 | -2^31 ~ 2^31-1 |
unsigned long | 4 | 0 ~ 2^32-1 |
long long | 8 | -2^63 ~ 2^63-1 |
unsigned long long | 8 | 0 ~ 2^64-1 |
计算机内存储数据是使用二进制来表示的。有符号类型的最高位会被用为符号位,而无符号类型则多了最高位用来表示数值。
计算机内是使用补码来存储整数的(正数补码是它本身,负数补码=对应正数原码取反+1)。以signed char类型为例,从概念上来说,0数值是可以分为+0(00000000)和-0(10000000)的,而这时候我们已经选择用+0来表示数字0了,-0就可以用于表示其他值,将-0采用补码规则是映射到-128的(正数128原码为010000000,取反为101111111,再+1为110000000,截掉前面的溢出位1结果为10000000),因此自然而然就用于表示-128了。
bool类型用于表示逻辑上的真和假,取值范围为字面值true和false,其可以提升为int类型——true转为1,false转为0。
另外值得注意的是,任何数字值或指针值都可以隐式转换为bool值,任何非零值转为true,而零值转为false。
前面提到,程序需要处理的字符集可能无法用一个8位的字节表示,此时C++有两种处理方式:一种是编译厂商可以将char定义为一个16位的字节或更长的字节(例如,在Java语言中char的长度就是2个字节);另一种是使用宽字符类型wchar_t来表示扩展字符集(wchar_t是整数类型,具体类型取决于系统实现),通常会将每个字符存储在一个2字节的内存单元中。
常见的浮点类型有float(单精度小数)、double(双精度小数)、long double。float和double的区别点在于,通常double类型能够表示的范围更大且精度更高。体现为double能够保证准确的有效位更多。
常见的5种基本算术操作符分为加(+)、减(-)、乘(*)、除(/)、取余(%)。
在C++ 中,一个 数据类型 的值可以被转换成另一种数据类型的值,这个转换就叫做类型转换。在进行类型转换时需要注意的是,如果是向上转型的转换(例如,float转double,int转long)通常是安全的,但如果是向下转型的转换(例如,long转int,double转float,浮点数转整数)就有可能会产生截断或精度丢失问题。
在C++ 中,按转换方式也可以大致划分为两种类型转换——隐式转换和显式转换。
由编译器自动完成的类型转换称为隐式转换,也称为自动转换。
例如,在计算表达式时,C++会将bool、char、unsigned char、signed char和short值转换为int,这些转换也被称为整型提升。
当用户手动将数据从一种类型更改为另一种类型时,这称为显式转换,主要有以下三种方式:
C 样式类型转换(也称为转换符号)
函数符号(也称为旧的 C++ 样式类型转换)
类型转换运算符(static_cast
、dynamic_cast
、const_cast
、reinterpret_cast
)
#include
using namespace std;
int main()
{
int num1 = 10;
short num2 = (short)num1; // 1、C风格转换
int num3 = 10;
long num4 = long(num3); // 2、旧的C++风格转换
int num5 = 10;
unsigned int num6 = static_cast(num5); // 3、使用了C++的类型转换运算符
return 0;
}