目录:
- 八进制和十六进制
- 其他整数类型
1.八进制和六进制
通常,C 语言都假定整型常量是十进制数。然而,许多程序员很喜欢使用八进制和十六进制数。因为8和16都是2的幂,而10却不是。显然,八进制和十六进制记数系统在表达与计算机相关的值时很方便。例如,十进制数65536经常出现在16位机中,用十六进制表示正好是10000。另外,十六进制数的每一位的数恰好由4位二进制数表示。例如,十六进制数3是0011,十六进制数5是0101。因此,十六进制数35的位组合(bit pattern)是00110101,十六进制数53的位组合是01010011。这种对应关系使得十六进制和二进制的转换非常方便。但是,计算机如何知道10000是十进制、十六进制还是二进制?在C语言中,用特定的前缀表示使用哪种进制。0x或0X前缀表示十六进制值,所以十进制数16表示成十六进制是0x10或0X10。与此类似,0前缀表示八进制。例如,十进制数16表示成八进制是020。第15章将更全面地介绍进制相关的内容。
要清楚,使用不同的进制数是为了方便,不会影响数被储存的方式。也就是说,无论把数字写成16、020或Ox10,储存该数的方式都相同,因为计算机内部都以二进制进行编码。
显示八进制和十六进制
在C程序中,既可以使用和显示不同进制的数。不同的进制要使用不同的转换说明。以十进制显示数字,使用%d;以八进制显示数字,使用%o;以十六进制显示数字,使用%×。另外,要显示各进制数的前缀0、0x和 0X,必须分别使用号%#o、%#x、%#X。
/*bases.c--以十进制、八进制、十六进制打印十进制数100?*/
#include<stdio.h>
int main(void)
{
int x=100;
printf("dec=%d;octal=%o;hex=%x\n",x,x,x);
printf("dec=%d;octal=%#o;hex=%#x\n",x,x,x);
return 0;
}
运行结果:
2.其他整数类型
C语言提供三个附属关键字修饰整数类型:short、long和unsigned。
- short int类型,占用的存储空间可能比int少,用于较小数值的场合以节省空间。与int类似,short是有符号类型。
- long int或long占用的存储空间可能比int多,适用于较大数值的场合。与int类似即,long是有符号类型。
- long long int或long long占用的存储空间可能比long多,适用于更大数值的场合。与int类似即,long long是有符号类型。
- unsigned int或unsigned只适用于非负值场合。这种类型和有符号类型表示的范围不同。例如,16位unsigned int允许的取值范围0~65535,而不是-32768~32767。用于表示正负号的位现在用于表示另一个二进制位,所以无符号整形可以表示更大的数。
- 在任何有符号类型前面添加关键字signed,可强调使用有符号类型的意图。
1.声明其他整数类型
long int estine;
long johns;
short int erns;
short ribs;
unsigned int s_count;
unsigned players;
unsigned long headcount;
unsigned short yesvotes;
long long ago;
2.使用多种整数类型的原因
为什么说short类型“可能”比int 类型占用的空间少,long类型“可能”比int 类型占用的空间多?因为C语言只规定了 short 占用的存储空间不能多于int,long 占用的存储空间不能少于int。这样规定是为了适应不同的机器。
3.long常量和long long常量
通常,程序代码中使用的数字(如,2345)都被储存为int类型。如果使用1000000这样的大数字,超出了int类型能表示的范围,编译器会将其视为long int 类型(假设这种类型可以表示该数字)。如果数字超出long可表示的最大值,编译器则将其视为unsigned long类型。如果还不够大,编译器则将其视为long long或unsigned long long 类型(前提是编译器能识别这些类型)。
八进制和十六进制常量被视为 int 类型。如果值太大,编译器会尝试使用unsigned int。如果还不够大,编译器会依次使用long、unsigned long、long long和unsigned long long 类型。有些情况下,需要编译器以long类型储存一个小数字。例如,编程时要显式使用IBMPC上的内存地址时。另外,一些C标准函数也要求使用long 类型的值。要把一个较小的常量作为long 类型对待,可以在值的末尾加上1(小写的 L)或 L 后缀。使用 L后缀更好,因为 1 看上去和数字 1很像。因此,在int为16位、long为32位的系统中,会把7作为16位储存,把7L作为32位储存。1或L后缀也可用于八进制和十六进制整数,如020L和0x10L。
类似地,在支持long long类型的系统中,也可以使用11或LL后缀来表示long long类型的值,
如3LL。另外,u或U后缀表示unsigned long long,如5ul1、10LLU、6LLU或9U11。
整数溢出
如果整数超出了相应类型的取值范围会怎样?下面分别将有符号类型和无符号类型的整数设置为比最大值略大,看看会发生什么(printf()函数使用%u说明显示unsigned int 类型的值)。
/* toobig.c-- 超出系统允许的最大int 值*/#include <stdio.h>
int main(void){
int i=2147483647;
unsigned int j= 4294967295;
printf("%d %d %d\n", i, i+1, i+2);
printf("%u %u %u\n",j,j+1, j+2);
return 0;}
在我们的系统下输出的结果是:
2147483647 -2147483648 -2147483647
4294967295 0 1
可以把无符号整数j看作是汽车的里程表。当达到它能表示的最大值时,会重新从起始点开始。整数i也是类似的情况。它们主要的区别是,在超过最大值时,unsigned int 类型的变量j从0开始;而int 类型的变量i则从-2147483648开始。注意,当i超出(溢出)其相应类型所能表示的最大值时,系统并未通知用户。因此,在编程时必须自己注意这类问题。
溢出行为是未定义的行为,C 标准并未定义有符号类型的溢出规则。以上描述的溢出行为比较有代表性,但是也可能会出现其他情况。
4. 打印 short、long、long long和unsigned 类型
打印 unsigned int 类型的值,使用%u 转换说明;打印 long 类型的值,使用%1d转换说明。如果系统中 int 和long 的大小相同,使用d就行。但是,这样的程序被移植到其他系统(int 和long 类型的大小不同)中会无法正常工作。在x和o前面可以使用1前缀,%1x表示以十六进制格式打印 long类型整数,$lo 表示以八进制格式打印 long 类型整数。注意,虽然 C 允许使用大写或小写的常量后缀,但是在转换说明中只能用小写。
C 语言有多种 printf()格式。对于 short 类型,可以使用 h 前缀。%hd 表示以十进制显示 short类型的整数,gho表示以八进制显示 short 类型的整数。h和1前缀都可以和u一起使用,用于表示无名号类型。例如,%lu 表示打印 unsigned long 类型的值。对于支持long long 类型的系统,%11d和%11u分别表示有符号和无符号类型。