C 如何处理带前导零的整数文字,“atoi”又如何?

问题描述 投票:0回答:8

当您创建一个带有前导零的整数时,C 如何处理它?不同版本的C有不同吗?

就我而言,它们似乎只是被丢弃了(但也许这就是

printf
的作用?):

#include <stdio.h>

int main() {
    int a = 005;
    printf("%i\n", a);
    return 0;
}

我知道我可以使用

printf
来填充 0,但我只是想知道这是如何工作的。

c literals
8个回答
38
投票

前导零表示该数字以 八进制 或基数 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,则该字符串可以 包括
"0x"
前缀和数字 将以 16 进制读取;否则,一个 零基数取为 10(十进制) 除非下一个字符是
'0'
,否则 在这种情况下,它被视为 8(八进制)。

所以它使用与 C 编译器相同的规则。


9
投票

前导零表示数字是八进制的这一事实经常被忘记。我曾多次看到它造成混乱,例如当有人尝试使用良好的常规八位字节格式输入 IP 地址时:

192.168.010.073

解析器将最后 2 个八位字节解释为八进制数。

唯一比 C 不幸使用前导零来使数字八进制更糟糕的是 Javascript 处理前导零来有时使数字八进制(如果其余数字都正常 - 小于 8 - 十进制,则该数字是八进制否则)。在 Javascript 中,

(017 == 15)
但是
(018 == 18)

我宁愿有一个错误;实际上我宁愿完全放弃八进制文字支持。至少使用一个更直接的前缀,比如也许

0t10  (ocTal 8)
0k17  (oKtal 15)

但我的提议迟了大约 35 年。


8
投票

小心!

在此语句中

005
是一个八进制常数。

int a = 005;

在这种情况下,这并不重要,因为一位八进制常量与等效的十进制常量具有相同的值,但在 C 中:

015 != 15

无论整数文字是用八进制、十进制还是十六进制表示,一旦被编译器解析,它就被视为一个值。如何通过

printf
输出整数仅取决于其类型、值和格式说明符(以及活动区域设置)。


5
投票

在所有版本的 C 中,带有前导零的数字表示八进制编码。所以

011 == 9 == 0x9

八进制是基于 8 的计数系统(而不是十进制的 10 或十六进制的 16)。所以

011 == 1*8 + 1, 013 == 1*8 + 3
等等


3
投票

你应该尝试:

int a = 5;
printf("%03i\n", a);

0 表示“用零填充”,3 是所需的输出长度。

编辑:抱歉,我读得太快了你的问题 - 现在我看到你问了一些完全不同的问题。不过,我会保持原样,因为它可能对其他人有帮助。


2
投票

0
开头的数字表示该数字是 八进制 数字。它称为“整数文字”。您还可以使用 0b 来表示
二进制数
,对于 十六进制数,它是 0x
0X
。您不需要为
decimal
编写任何内容。请参阅下面的代码。 #include<stdio.h> int main() { int binary = 0b10; int octal=010; int decimal = 10; int hexa = 0x10; printf("%d %d %d %d\n", octal, decimal, hexa, binary); }

欲了解更多信息,请访问
tutorialspoint


1
投票


1
投票
在您的特定情况下,printf 会删除零。

除了初始零之外,所有前导零都会被编译器删除,这会导致编译器将整数视为八进制。对于 005,八进制和十进制表示形式是相同的,不应该打扰您,但除非您特别指的是八进制表示形式,否则它仍然会带来麻烦。 前导零必须纯粹与整数的字符串表示有关。要打印前导零,请使用“%03d”。这将确保字段长度为 3。

一般来说,“%

d”将打印一个整数 x 个字符宽,并用前导空格填充。 “%0

d”会做同样的事情,但会用前导零填充。

© www.soinside.com 2019 - 2024. All rights reserved.