当您创建一个带有前导零的整数时,C 如何处理它?不同版本的C有不同吗?
就我而言,它们似乎只是被丢弃了(但也许这就是
printf
的作用?):
#include <stdio.h>
int main() {
int a = 005;
printf("%i\n", a);
return 0;
}
我知道我可以使用
printf
来填充 0,但我只是想知道这是如何工作的。
前导零表示该数字以 八进制 或基数 8 表示;因此,010 = 8。添加额外的前导零没有效果;正如您在数学中所期望的那样,x + 0*8^n = x;通过延长其表示形式并不会改变该值。
您经常看到这种情况的一个地方是 UNIX 文件模式; 0755实际上意味着7*8^2+5*8+5 = 493;或使用 umask,例如 0022 = 2*8+2 = 10。
atoi(nptr)
定义为与 strtol(nptr, (char **) NULL, 10)
等效,但它不检测错误 - 因此,atoi()
始终使用十进制(因此忽略前导零)。 strtol(nptr, anything, 0)
执行以下操作:
字符串可以任意开头 空白量(根据确定 由
) 后跟一个 可选isspace(3)
或'+'
符号。如果基数是 零或 16,则该字符串可以 包括'-'
前缀和数字 将以 16 进制读取;否则,一个 零基数取为 10(十进制) 除非下一个字符是"0x"
,否则 在这种情况下,它被视为 8(八进制)。'0'
所以它使用与 C 编译器相同的规则。
前导零表示数字是八进制的这一事实经常被忘记。我曾多次看到它造成混乱,例如当有人尝试使用良好的常规八位字节格式输入 IP 地址时:
192.168.010.073
解析器将最后 2 个八位字节解释为八进制数。
唯一比 C 不幸使用前导零来使数字八进制更糟糕的是 Javascript 处理前导零来有时使数字八进制(如果其余数字都正常 - 小于 8 - 十进制,则该数字是八进制否则)。在 Javascript 中,
(017 == 15)
但是 (018 == 18)
。
我宁愿有一个错误;实际上我宁愿完全放弃八进制文字支持。至少使用一个更直接的前缀,比如也许
0t10 (ocTal 8)
0k17 (oKtal 15)
但我的提议迟了大约 35 年。
小心!
在此语句中
005
是一个八进制常数。
int a = 005;
在这种情况下,这并不重要,因为一位八进制常量与等效的十进制常量具有相同的值,但在 C 中:
015 != 15
无论整数文字是用八进制、十进制还是十六进制表示,一旦被编译器解析,它就被视为一个值。如何通过
printf
输出整数仅取决于其类型、值和格式说明符(以及活动区域设置)。
在所有版本的 C 中,带有前导零的数字表示八进制编码。所以
011 == 9 == 0x9
。
八进制是基于 8 的计数系统(而不是十进制的 10 或十六进制的 16)。所以
011 == 1*8 + 1, 013 == 1*8 + 3
等等
你应该尝试:
int a = 5;
printf("%03i\n", a);
0 表示“用零填充”,3 是所需的输出长度。
编辑:抱歉,我读得太快了你的问题 - 现在我看到你问了一些完全不同的问题。不过,我会保持原样,因为它可能对其他人有帮助。
除了初始零之外,所有前导零都会被编译器删除,这会导致编译器将整数视为八进制。对于 005,八进制和十进制表示形式是相同的,不应该打扰您,但除非您特别指的是八进制表示形式,否则它仍然会带来麻烦。
前导零必须纯粹与整数的字符串表示有关。要打印前导零,请使用“%03d”。这将确保字段长度为 3。
一般来说,“%
d”将打印一个整数 x 个字符宽,并用前导空格填充。 “%0d”会做同样的事情,但会用前导零填充。