GCC 将int i=048;
其视为错误,因为048
应该是八进制数,但8
不能出现在八进制数中。
但是为什么 GCC 不能更智能,把 is 当作十进制数呢?
因为如果将 048 解释为十进制,它将违反语言“C”的句法规则。任何以 0 开头的数字都应解释为“八进制”。
这是一件好事,因为编译器努力做到符合标准。
还假设您正在为自己的 C 编译器编写 C 解析器,它实际上可以“理解”您的意思048, 049..
是所有十进制数。现在你将如何制作那个解析器?它可能但令人难以置信的复杂。以及大量错误的来源。
这并不是 GCC 的错,因为它努力符合标准。
但是想象一下,如果它确实排除了“如果数字标记以 0 开头但不是八进制,则将其视为十进制”的形式。这条规则不仅相对复杂——“如果代码以通常的方式没有意义,则回退到另一种解释,看看它是否有意义”——而且它还呈现出各种其他意想不到的行为:
/* My bearings */
int east = 000; // 0 in Octal = 0
int northeast = 045; // 45 in Octal = 37
int north = 090; // Starts with 0 but contains 9, must be decimal = 90
int northwset = 135; // Starts with 1, is decimal = 135
...
确实,具有现有行为的类似代码也可以通过编译器并带有变量的意外值。关键是添加一个特殊规则来帮助您的案例将留下其他案例。最好是捕获错误并将其视为错误,而不是找出其中一些可以不同的解释。
(FWIW,我从来没有使用过八进制表示法,并且发现它的存在很可怕,因为在许多其他情况下,我会用 0 填充十进制数字来表示。记住永远不要在 C 中这样做需要一点额外的脑力。)
C 语言要求在这种情况下发出诊断(错误)。GCC 必须遵守。
除此之外,您提倡的行为类型是极其有害的。它会掩盖各种错误/错别字,并引入非常混乱的不一致。例如,如果某些代码包含:
int x = 01800;
而您将 更改18
为20
, 的值x
实际上会减少!
如果您输入,您会期望更高的智能gcc
必须做什么
int i=047;
...然后,随后,如果您的一位同事将程序更改为阅读,您会期待什么
int i=049;
..您和他或她会因为仅添加“2”而得知值已从 更改为39
!49
最小惊讶原则有助于指导各种设计人员,毫无疑问,这可能是 C 语言设计中的一个因素。
也就是说,更不令人惊讶的是八进制文字,它不仅仅是一个前导零。为此,像 python 和 rust 这样的语言将八进制编码为“ 0o47
”(类似于 C 等人的十六进制文字)。