C如何处理带有前导零的整数文字,以及atoi怎么样?

Kyl*_*ndt 8 c literals

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

在我的情况下,它们似乎只是被丢弃(但也许这就是printf的作用?):

#include <stdio.h>

int main() {
    int a = 005;
    printf("%i\n", a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用printf来填充0,但我只是想知道它是如何工作的.

bdo*_*lan 33

前导零表示该数字以八进制表示,或以8为基数表示; 因此,010 = 8.添加额外的前导零没有效果; 正如你在数学中所期望的那样,x + 0*8 ^ n = x; 通过使其表示更长时间来改变价值.

您经常看到的一个地方是UNIX文件模式; 0755实际上意味着7*8 ^ 2 + 5*8 + 5 = 493; 或者使用诸如0022 = 2*8 + 2 = 10之类的umasks.

atoi(nptr)被定义为等价strtol(nptr, (char **) NULL, 10),除了它不检测错误 - 因此,atoi()总是使用小数(因此忽略前导零).strtol(nptr, anything, 0)执行以下操作:

字符串可以以任意数量的空白区域(由确定isspace(3))开始,后跟单个可选'+''-'符号.如果base为0或16,则该字符串可以包括"0x"前缀,并且该数字将在base 16中读取; 否则,零基数被视为10(十进制),除非下一个字符是'0',在这种情况下,它被视为8(八进制).

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


CB *_*ley 7

小心!

在这个语句中005是一个八进制常量.

int a = 005;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,无关紧要,因为单个数字八进制常量与等效的十进制常数具有相同的值但在C中: 015 != 15

整数文字是用八进制,十进制还是十六进制表示,一旦被编译器解析,它就被视为一个值.如何输出整数printf仅取决于其类型,值和格式说明符(以及活动区域设置).


Mic*_*urr 7

前导零表示数字是八进制的事实是经常被遗忘的事实.我已经看到它多次引起混淆,例如当有人试图使用一个漂亮的,常规格式的八位字节输入IP地址时:

192.168.010.073
Run Code Online (Sandbox Code Playgroud)

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

唯一比C不幸使用前导零来制作数字八进制更糟糕的是Javascript处理前导零有时会产生一个数字八进制(如果其余数字都可以,则数字为八进制 - 否则小于8 - 十进制).在Javascript中,(017 == 15)但是(018 == 18).

我宁愿有一个错误; 实际上我宁愿完全放弃八字形文字支持.至少可以使用更多的面对面的前缀

0t10  (ocTal 8)
0k17  (oKtal 15)
Run Code Online (Sandbox Code Playgroud)

但是我提议的时间已经晚了35年.


Aar*_*lla 5

具有前导零的数字表示在所有C版本中的八进制编码011 == 9 == 0x9.

Octal是一个基于8的编号系统(而不是10为十进制或16为十六进制).所以011 == 1*8 + 1, 013 == 1*8 + 3,等等