1.二进制、八进制和十六进制
1.1 二进制、八进制和十六进制数的表示
一个数字默认就是十进制的,表示一个十进制数字不需要任何特殊的格式。但是,表示一个二进制、八进制或者十六进制数字就不一样了,为了和十进制数字区分开来,必须采用某种特殊的写法,具体来说,就是在数字前面就上特定的字符,也就是加前缀。
(1)、二进制
二进制由 0 和 1两个数字组成,使用时必须以0b 或0B(不区分大小写)开头,例如:
// 合法的二进制
int a = 0b101; // 换算成十进制为
int b = -0b110010; // 换算成十进制为
int c = 0B100001; // 换算成十进制为
// 非法的二进制
int m = 101010; // 无前缀 0B,相当于十进制
int n = 0B410; // 4不是有效的二进制数字
请注意,标准的C/C++语言并不支持二进制的写法,只是有些编译器自己进行了扩展,才支持二进制数字。换句话说,并不是所有的编辑器都支持二进制数字,只有一部分呢编辑器支持,并且跟编辑器的版本有关系。
(2)、八进制
八进制由0-7 八个数字组成,使用时必须以 0 开头,(注意是数字0,不是字母o),例如:
// 合法的八进制
int a = 015; // 换算成十进制为
int b = -0101; // 换算成十进制为
int c = 0177777; // 换算成十进制为
// 非法的八进制
int m = 256; // 无前缀 0,相当于十进制
int n = 03A2; // A不是有效的八进制数字
(3)、十六进制
十六进制由数字 0-9、字母A-F或a-f(不区分大小写)组成,使用时必须以0x或0X(不区分大小写)开头,例如:
// 合法的十六进制
int a = 0X2A; // 换算成十进制为
int b = -0XA0; // 换算成十进制为
int c = 0xffff; // 换算成十进制为
// 非法的十六进制
int m = 5A; // 无前缀0X,是一个无效数字
int n = 0X3H; // H不是有效的十六进制数字
(4)、十进制
十进制由0-9十个数字组成,没有任何前缀,和我们平时的书写格式一样,不再赘述。
1.2、二进制、八进制和十六进制数的输出
C/C++语言中常用的整数有short、int和long三种类型,通过printf函数,可以将它们以八进制、十进制和十六进制的格式输出。
short | int | long | |
八进制 | %ho | %o | %lo |
十进制 | %hd | %d | %ld |
十六进制 | %hx 或者 %hX | %x 或者 %X | %lx 或者 %lX |
十六进制数字表示用到了英文字母,有大小写之分,要在格式控制中体现出来:
(1)、%hx、%x、%lx中的x小写,表明以小写字母的形式输出十六进制;
(2)、%hX、%X、%lX中X的大写,表明以大写字母的形式输出十六进制。
八进制数字和十进制数字不区分大小写,所以格式控制符都用小写形式。如果使用大写形式,那么行为是未定义的!
(1)、有些编辑器支持大写形式,只不过行为和小写形式一样;
(2)、有些编辑器不支持大写形式,可能会报错,也可能会导致奇怪的输出。
注意:虽然部分编辑器支持二进制数字的表示,但是却不能使用printf函数输出二进制,这一点比较遗憾。
[实例]
#include <stdio.h>
int main()
{
short a = 0b1010110; // 二进制数字
int b = 02713; // 八进制数字
long c = 0X1DAB83; // 十六进制数字
printf(“a = %ho, a = %hd, a = %hx, a = %hX”, a, a, a, a);
printf(“b = %o, b = %d, b = %x, b = %X”, b, b, b, b);
printf(“c = %lo, c = %ld, c = %lx, c = %lX”, c, c, c, c);
return 0;
}
运行结果:
1.3 输出时加上前缀
请观察以上的例子,会发现有一点不完美,如果只看输出结果:
(1)、对于八进制数字,它没法和十进制、十六进制区分,因为八进制、十进制和十六进制都包含0-7这几个数字。
(2)、对于十进制数字,它没法和十六进制区分,因为十六进制也包含0-9这几个数字。如果十进制数字中还不包含8和9,那么也不能和八进制区分了。
(3)、对于十六进制,如果没有包含a-f或者A-F,那么就无法和十进制区分,如果还不包含8和9,那么也不能和八进制区分了。
区分不同进制数字的一个简单办法就是,在输出时带上特定的前缀。在格式控制符中加上#即可输出前缀,例如%#ho,%#hx,%#hX %#o,%#x,%#X %#lo,%#lx,%#lX
[实例]
#include <stdio.h>
int main()
{
short a = 0b1010110; // 二进制数字
int b = 02713; // 八进制数字
long c = 0X1DAB83; // 十六进制数字
printf(“a = %#ho, a = %hd, a = %#hx, a = %#hX”, a, a, a, a);
printf(“b = %#o, b = %d, b = %#x, b = %#X”, b, b, b, b);
printf(“c = %#lo, c = %ld, c = %#lx, c = %#lX”, c, c, c, c);
return 0;
}
运行结果:
十进制数字没有前缀,所以不用加#,如果加上了,那么它的行为是未定义的,有的编译器支持十进制加#,只不过输出结果和没有加#一样,有的编译器不支持加#,可能会报错,也可能会导致奇怪的输出;但是,大部分编译器都能正常输出,不至于当成一种错误。