C语言支持两种不同的数值类型,整数类型(也称整型),浮点类型(也称浮点型)。整数类型的值是整数,而浮点类型的值则可能还有小数部分。
整数类型又分为两大类:有符号型和无符号型。
有符号整数如果为正数或零,那么最左边的位(符号位)为0;如果为负数,则符号位为1。因此,最大的16位整数的二进制表示形式是0111 1111 1111 1111,对应的值是32767(即2^15-1)。而最大的32位整数是0111 1111 1111 1111 1111 1111 1111 1111,对应的数值是2147483647(即2^31-1)。
不带符号位的整数(最左边的位是数值的一部分)的整数称为无符号整数。最大的16位无符号整数是65535(即2^16-1),而最大的32位无符号整数是4294967295(即2^32-1)。
默认情况下,C语言中的整型变量都是有符号的,也就是说最左位保留为符号位。若要告诉编译器变量没有符号位,需要把它声明成unsigned类型。无符号整数主要用于系统编程和底层与机器相关的应用。
C语言还提供了四个可以修饰int的关键字:short、long、signed,以及unsigned。利用这四个关键字,C语言标准定义了以下整数类型:
1) short int(可简写为 short)
2) int
3) long int(简写:long)
4) long long int(简写:long long)
5) unsigned short int(简写:unsigned short)
6) unsigned int
7) unsigned long int(简写:unsigned long)
8) unsigned long long int(简写:unsigned long long)
有没有signed都表示有符号整数,例如:signed int等同于int。
一般我们把short称为短整型,把long称为长整型,把long long称为超长整型,把int称为整型。unsigned打头的那些整数类型统称为无符号整型。例如:我们称unsigned short为无符号短整型,以此类推。
C语言只规定short <= int <=long int。具体还得看具体的编译器,long int型并不能肯定就是64位的,很多时候long int和int表示的范围是一致的。
在16位操作系统(例如DOS)中,一般用2字节存放一个int型数据;在32位操作系统(例如Windows98)中,默认为4字节。各类整型数据的长度及读写格式见下表:
常量是在程序中以文本形式出现的数,而不是读、写或计算出来的数。C语言允许用十进制(基数为10)、八进制(基数为8)和十六进制(基数为16)形式书写整数常量。
八进制数是用数字0~7书写的。八进制数的每一位表示一个8的幂(这就如同十进制数的每一位表示10的幂一样)。因此,八进制的数237表示成十进制数就是2x8^2+3x8^1+7x8^0=128+24+7=159。
十六进制数是用数字0~9加上字母A~F书写的,其中字母A~F表示10~15的数。十六进制数的每一位表示一个16的幂,十六进制数1AF的十进制数值是1x16^2+10x16^1+15x16^0=256+160+15=431。
十进制常量包含0~9中的数字,但是一定不能以零开头:15 255 32767
八进制常量只包含0~7中的数字,而且必须要以零开头:017 0377 077777
十六进制常量包含0~9中的数字和a~f中的字母,而且总是以0x开头:0xf 0xff 0x7fff
十六进制常量中的字母既可以是大写字母也可以是小写字母:0xf 0xFF 0x7fFF
八进制和十六进制只是书写数的方式,它们不会对数的实际存储方式产生影响。整数都是以二进制形式存储的,跟表示方式无关。任何时候都可以从一种书写方式切换到另一种书写方式,甚至可以混合使用:10+015+0x20的值为55(十进制)。
十进制整数常量的类型通常为int,但如果常量的值大得无法存储在int型中,就用long int类型。如果出现long int不够用的情况,则用unsigned long int作最后的尝试。确定八进制和十六进制常量的规则时,编译器会依次尝试int、unsigned int、long int和unsigned long int类型,直到找到能表示该常量的类型。
C99确定整数常量类型的规则与C89有些不同。对于没有后缀(U、u、L、l、LL、ll)的十进制常量,其类型是int、long int或long long int中能表示该值的“最小”类型。对于八进制或者十六进制常量,可能的类型顺序为int、unsigned int、long int、unsigned long int、long long int和unsigned long long int。常量后面的任何后缀都会改变可能类型的列表。例如,以U(或u)结尾的常量类型一定是unsigned int、unsigned long int和unsigned long long int中的一种。
为了强制编译器把常量作为长整数来处理,只需在后边加上一个字母L(或l):
15L 0377L 0x7fffL
为了指明是无符号常量,可以在常量后边加上字母U(或u):
15U 0377U 0x7fffU
L和U可以结合使用,以表明常量既是长整型又是无符号的:0xffffffffUL。(字母L、U的顺序和大小写无所谓。)
在C99中,以LL或ll(两个字母大小写要一致)结尾的整数常量是long long int型的。如果在LL或ll的前面或后面增加字母U(或u),则该整数常量为unsigned long long int型。
对整数执行算数运算时,其结果有可能因为太大而无法表示。例如,对两个int值进行算术运算时,结果必须仍然能用int类型来表示;否则(表示结果所需的数位太多)就会发生溢出。
整数溢出时的行为要根据操作数是有符号型还是无符号型来确定。有符号整数运算中发生溢出时,程序的行为是未定义的,未定义行为的结果是不确定的。最可能的情况是,仅仅是运算的结果出错了,但程序也有可能崩溃,或出现其他意想不到的情况。
无符号整数运算过程中发生溢出时,结果是有定义的:正确答案对2^n取模,其中n是用于存储结果的位数,例如,如果对无符号的16位数65535加1,其结果可以保证为0。
读写无符号整数、短整数和长整数需要转换说明符。
读写无符号整数时,使用字母u、o或x代替转换说明中的d。如果使用u说明符,该数将以十进制形式读写,o表示八进制形式,而x表示十六进制形式。
unsigned int u;
scanf("%u", &u); /* reads u in base 10 */
printf("%u", u); /* writes u in base 10 */
scanf("%o", &u); /* reads u in base 8 */
printf("%o", u); /* writes u in base 8 */
scanf("%x", &u); /* reads u in base 16 */
printf("%x", u); /* writes u in base 16 */
读写短整数时,在d、o、u或x前面加上字母h:
short s;
scanf("%hd", &s);
printf("%hd", s);
读写长整数时,在d、o、u或x前面加上字母l:
short l;
scanf("%ld", &l);
printf("%ld", l);
读写长长整数时(仅限C99),在d、o、u或x前面加上字母ll:
short ll;
scanf("%lld", &ll);
printf("%lld", ll);