新的C语言标准增加了long long和long double类型表示长整型和长浮点型,但C语言并未定义基本数据类型所占的字节数,而是交给编译器决定,大部分C编译器和高级语言对于基本数据类型的定义大致相同,记住基本数据的类型和范围是有必要的。
类型 字节数 取值范围
char 1 -127-127
unsigned char 1 0-256
short 2 -32767-32767
unsigned short 2 0-65535
int 4 -2147483648-2147483648
unsigned 4 0-4294967295
long 8 -9223372036854775808-9223372036854775808
unsigned long 8 0-18446744073709551615
float 4 7位有效数字
double 8 16位有效数字
上面表格指的是64位系统,一般在32位软件中int是2位,long是4位,double是4位,但通过long long和long double仍然可以达到8位,与之对应的无符号类型为unsigned long long和unsigned long double。可以在数字后面加L来区分是否是长整数,100L为long, 100LL为long long。在64位系统中4位整数就可以达到21亿,8位整数可以达到9 亿亿,通常4位已经够用,除非特别大的数值才会用到long。有符号整数第一位为符号位,因此取值范围要比无符号整数小一半。为了简化电路设计,计算机将减法换算成加法,因此整数在内存中以补码的形式存放,正数的补码是原码,负数的补码是其反码+1,无论正负将两个补码相加后再还原就可以得到正确的值,这是一个天才的设计,也是cpu计算的基本法则之一,这也解释了为什么用无符号整数去显示一个负数会得到一个很大的值,因为负数通常是1111 1111 1111 1110这样高位都是1的二进制数。C编译器不会检查数值溢出,数值溢出后会得到一个奇怪的数,这往往会导致程序崩溃。
浮点由于使用指数形式,也就是科学计数法,大小范围可已远超日常应用,需要关心的是精度,对于无限循环小数和无限不循环小数,精度越大越好,因此使用1/3.0形式求值时得到的是双精度值。浮点在计算机中也会转换为二进制,例如1.01101*2110,由于整数部分1和基数2不变,浮点值只需记录小数部分和指数即可,在C中:
float结构为
符号位 指数 小数
1bit 8bits 23bits
double结构为
符号位 指数 小数
1bit 11bits 52bits
因此如果将浮点所储存的内容当作整数来读取时,也会得到一个奇怪的值,把浮点转化为整数会截掉小数,双精度转化为单精度会进行四舍五入,如果不使用强制转化编译器不会报错但会给出警告。浮点不仅储存格式复杂,加减乘除运算也很复杂,而且在cpu发展初期每个厂商的定义的规则也不相同,很多低级的cpu根本不支持浮点运算,后来intel邀请加州大学伯克利分校的 William Kahan 教授制定了一套定义和运算规则,称为IEEE 754,这里面还蕴含了一个图灵奖。IEEE 754除了标准化存储方式和计算方式外还定义了3个特殊值:正无穷大、负无穷大和NaN值,当数值太大超过浮点能表示的边界时,值为inf或infinity。当值无效时,例如给asin()传入大于1的数会返回NaN。C语言遵守IEEE 754标准,但特殊值的表示方法取决于编译器。
bool 是新标准定义的类型,值可以为true和false,但是要导入头文件stdbool.h,如果不导入只能使用内置_Bool类型,且用整数0和1表示真假,导入后true被定义成常量1,false被定义成常量0。
sizeof()函数可以测量出各种数据类型的长度,这包含基本数据类型、自定义数据类型、数组、指针等,也可以对变量和常量测量大小,例如:
sizeof(int)
sizeof(100);
sizeof(“student”)
sizeof(“汉字”);
sizeof可以求出数组所有元素的字节大小,但不能求出申请的堆大小,这些问题会在后面详细讲述。