一、二进制数、八进制数和十六进制数的表示
1.1 不同进制数的表示
一个数字默认就是十进制的,表示一个十进制数字不需要任何特殊的格式。但是,表示一个二进制、八进制或者十六进制数字就不一样了,为了和十进制数字区分开来,必须采用某种特殊的写法,具体来说,就是在数字前面加上特定的字符,也就是加前缀。
1.2 二进制
二进制由 0 和 1 两个数字组成,使用时必须以0b或0B(不区分大小写)开头,例如:
|
|
注意,标准的C语言并不支持上面的二进制写法,只是有些编译器自己进行了扩展,才支持二进制数字。换句话说,并不是所有的编译器都支持二进制数字,只有一部分编译器支持,并且跟编译器的版本有关系。
1.3 八进制
八进制由 0~7 八个数字组成,使用时必须以0开头(注意是数字 0,不是字母 o),例如:
|
|
1.4 十六进制
十六进制由数字 0~9、字母 A~F 或 a~f(不区分大小写)组成,使用时必须以0x或0X(不区分大小写)开头,例如:
|
|
二、格式控制符
2.1 格式控制符列表
格式控制符 是以%开头,后跟数据类型控制说明字符的站位符。 格式控制符:
格式控制符 | 说明 |
---|---|
%c | 输出一个单一的字符 |
%hd、%d、%ld | 以十进制、有符号的形式输出 short、int、long 类型的整数 |
%hu、%u、%lu | 以十进制、无符号的形式输出 short、int、long 类型的整数 |
%ho、%o、%lo | 以八进制、不带前缀、无符号的形式输出 short、int、long 类型的整数 |
%#ho、%#o、%#lo | 以八进制、带前缀、无符号的形式输出 short、int、long 类型的整数 |
%hx、%x、%lx | 以十六进制、不带前缀、无符号的形式输出 short、int、long 类型的整数,输出的十六进制数字小写 |
%hX、%X、%lX | 以十六进制、不带前缀、无符号的形式输出 short、int、long 类型的整数,输出的十六进制数字大写 |
%#hx、%#x、%#lx | 以十六进制、带前缀、无符号的形式输出 short、int、long 类型的整数,输出的十六进制数字和前缀都小写 |
%#hX、%#X、%#lX | 以十六进制、带前缀、无符号的形式输出 short、int、long 类型的整数,输出的十六进制数字和前缀都大写 |
%f、%lf | 以十进制的形式输出 float、double 类型的小数 |
%e、%le | 以指数的形式输出 float、double 类型的小数,输出结果中的 e 小写 |
%E、%lE | 以指数的形式输出 float、double 类型的小数,输出结果中的 E 大写 |
%g、%lg | 十进制和指数中较短的形式输出 float、double 类型的小数,并且小数部分的最后不会添加多余的 0,当以指数形式输出时 e 小写 |
%G、%lG | 以十进制和指数中较短的形式输出 float、double 类型的小数,并且小数部分的最后不会添加多余的 0,当以指数形式输出时 E 也写 |
%s | 输出一个字符串 |
%p | 输出指针(内存地址) |
在编写代码的过程中,我建议将格式控制符和数据类型严格对应起来,养成良好的编程习惯。 当使用%d输出 short,或者使用%ld输出 short、int 时,不管值有多大,都不会发生错误,因为格式控制符足够容纳这些值。 当使用%hd输出 int、long,或者使用%d输出 long 时,如果要输出的值比较小(就像上面的情况),一般也不会发生错误,如果要输出的值比较大,就很有可能发生错误。
严格来说,格式控制符和整数的符号是紧密相关的,具体就是:
- %d 以十进制形式输出有符号数;
- %u 以十进制形式输出无符号数;
- %o 以八进制形式输出无符号数;
- %x 以十六进制形式输出无符号数。
printf 并不支持,也没有对应的格式控制符以八进制和十六进制形式输出有符号数。 下表全面地总结了不同类型的整数,以不同进制的形式输出时对应的格式控制符(–表示没有对应的格式控制符)。
short | int | long | unsigned short | unsigned int | unsigned long | |
---|---|---|---|---|---|---|
八进制 | – | – | – | %ho | %o | %lo |
十进制 | %hd | %d | %ld | %hu | %u | %lu |
十六进制 | – | – | – | %hx 或者 %hX | %x 或者 %X | %lx 或者 %lX |
- 当以有符号数的形式输出时,printf 会读取数字所占用的内存,并把最高位作为符号位,把剩下的内存作为数值位;
- 当以无符号数的形式输出时,printf 也会读取数字所占用的内存,并把所有的内存都作为数值位对待。
对于一个有符号的正数,它的符号位是 0,当按照无符号数的形式读取时,符号位就变成了数值位,但是该位恰好是 0 而不是 1,所以对数值不会产生影响,这就好比在一个数字前面加 0,有多少个 0 都不会影响数字的值。 如果对一个有符号的负数使用 %o 或者 %x 输出,那么结果就会大相径庭。
2.2 printf()
格式控制符的完整形式
printf() 格式控制符的完整形式如下:
|
|
[ ] 表示此处的内容可有可无,是可以省略的。
-
type 表示输出类型,比如 %d、%f、%c、%lf,type 就分别对应 d、f、c、lf;再如,%-9d中 type 对应 d。 type 这一项必须有,这意味着输出时必须要知道是什么类型。
-
width 表示最小输出宽度,也就是至少占用几个字符的位置;例如,%-9d中 width 对应 9,表示输出结果最少占用 9 个字符的宽度。
当输出结果的宽度不足 width 时,以空格补齐(如果没有指定对齐方式,默认会在左边补齐空格);当输出结果的宽度超过 width 时,width 不再起作用,按照数据本身的宽度来输出。
- .precision 表示输出精度,也就是小数的位数。 当小数部分的位数大于 precision 时,会按照四舍五入的原则丢掉多余的数字; 当小数部分的位数小于 precision 时,会在后面补 0。
另外,.precision 也可以用于整数和字符串,但是功能却是相反的:
- 用于整数时,.precision 表示最小输出宽度。与 width 不同的是,整数的宽度不足时会在左边补 0,而不是补空格。
- 用于字符串时,.precision 表示最大输出宽度,或者说截取字符串。当字符串的长度大于 precision 时,会截掉多余的字符;当字符串的长度小于 precision 时,.precision 就不再起作用。
|
|
- flag 是标志字符。例如,%#x中 flag 对应 #,%-9d中 flags 对应-。下表列出了 printf() 可以用的 flag:
标志字符 | 含义 |
---|---|
- | -表示左对齐。如果没有,就按照默认的对齐方式,默认一般为右对齐。 |
+ | 用于整数或者小数,表示输出符号(正负号)。如果没有,那么只有负数才会输出符号。 |
空 | 格 用于整数或者小数,输出值为正时冠以空格,为负时冠以负号。 |
# | 对于八进制(%o)和十六进制(%x / %X)整数,# 表示在输出时添加前缀;八进制的前缀是 0,十六进制的前缀是 0x / 0X。对于小数(%f / %e / %g),# 表示强迫输出小数点。如果没有小数部分,默认是不输出小数点的,加上 # 以后,即使没有小数部分也会带上小数点。 |
|
|