C 如何处理带前导零的整数文字,“atoi”又如何?
当创建一个带有前导零的整数时,C 如何处理它?不同版本的C有不同吗?
就我而言,它们似乎只是被删除了(但也许这就是 printf
所做的?):
#include <stdio.h>
int main() {
int a = 005;
printf("%i\n", a);
return 0;
}
我知道我可以使用 printf
来填充 0,但我只是想知道这是如何工作的。
When you create an integer with leading zeros, how does C handle it? Is it different for different versions of C?
In my case, they just seem to be dropped (but maybe that is what printf
does?):
#include <stdio.h>
int main() {
int a = 005;
printf("%i\n", a);
return 0;
}
I know I can use printf
to pad with 0s, but I am just wondering how this works.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
前导零表示该数字以八进制或基数 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, everything, 0)
执行以下操作:因此它使用与 C 编译器相同的规则。
Leading zeros indicate that the number is expressed in octal, or base 8; thus, 010 = 8. Adding additional leading zeros has no effect; just as you would expect in math, x + 0*8^n = x; there's no change to the value by making its representation longer.
One place you often see this is in UNIX file modes; 0755 actually means 7*8^2+5*8+5 = 493; or with umasks such as 0022 = 2*8+2 = 10.
atoi(nptr)
is defined as equivalent tostrtol(nptr, (char **) NULL, 10)
, except that it does not detect errors - as such,atoi()
always uses decimal (and thus ignores leading zeros).strtol(nptr, anything, 0)
does the following:So it uses the same rules as the C compiler.
前导零表示数字是八进制的这一事实经常被忘记。我已经多次看到它引起混乱,例如当有人尝试使用良好的常规八位位组格式输入 IP 地址时:
解析器将最后 2 个八位位组解释为八进制数。
唯一比 C 不幸使用前导零来生成八进制数字更糟糕的是 Javascript 处理前导零有时生成八进制数字(如果其余数字都正常,则该数字是八进制 - less小于 8 - 否则为十进制)。在 Javascript 中,
(017 == 15)
但(018 == 18)
。我宁愿有一个错误;实际上我宁愿完全放弃八进制文字支持。至少使用一个更直接的前缀,比如“maybe”,“
But I'm about 35年后才提出我的建议”。
The fact that a leading zero indicates a number is octal is something that's often forgotten. I've seen it cause confusion several times, such as when someone tried to input an IP address using a nice, regular format for the octets:
and the parser interpreted the last 2 octets as octal numbers.
The only thing worse than C's unfortunate use of leading zeros to make a number octal is Javascript's handling of leading zeros to sometimes make a number octal (the number is octal if the rest of the digits are OK - less than 8 - decimal otherwise). In Javascript,
(017 == 15)
but(018 == 18)
.I'd rather there be an error; actually I'd rather drop octal literal support altogether. At least use a more in-your-face prefix, like maybe
But I'm about 35 years too late with my proposal.
当心!
在此语句中,
005
是一个八进制常量。在这种情况下,这并不重要,因为一位八进制常量与等效的十进制常量具有相同的值,但在 C 中:
015 != 15
整数文字是否以八进制、十进制或十六进制表示,一旦被编译器解析,它就被视为一个值。整数如何通过 printf 输出仅取决于其类型、值和格式说明符(以及活动区域设置)。
Be careful!
In this statement
005
is an octal constant.In this case it doesn't matter because a single digit octal constant has the same value as the equivalent decimal constant but in C:
015 != 15
Whether an integer literal is expressed in octal, decimal or hexadecimal, once it is parsed by the compiler it is just treated as a value. How an integer is output via
printf
depends only on its type, its value and the format specifiers (and the active locale).带有前导零的数字表示所有版本的 C 中的八进制编码。因此
011 == 9 == 0x9
。八进制是基于 8 的计数系统(而不是十进制的 10 或十六进制的 16)。所以
011 == 1*8 + 1、013 == 1*8 + 3
等。A number with a leading zero means octal encoding in all versions of C. So
011 == 9 == 0x9
.Octal is a numbering system based on 8 (instead of 10 for decimal or 16 for hex). So
011 == 1*8 + 1, 013 == 1*8 + 3
, etc.您应该尝试:
0 表示“用零填充”,3 是所需的输出长度。
编辑:抱歉,我读得太快了 - 现在我发现你问的是完全不同的问题。不过,我会保留原样,因为它可能对其他人有帮助。
You should try:
0 means "pad with zeroes", 3 is the desired length of output.
Edit: Sorry, I've read your question too quickly - now I see you've asked about something completely different. However I'll leave this as is, as it might be helpful for someone else.
以
0
开头的数字表示该数字是一个八进制数字。它称为整数文字。您还可以使用0b
来表示二进制数,对于十六进制数,它是0x
或0X< /代码>。您不需要为十进制编写任何内容。请参阅下面的代码。
有关更多信息,请访问 tutorialspoint。
A number with leading
0
denoted that the number is an octal number. It's called Integer Literals. You can also use0b
for denoting binary number, for hexadecimal number it is0x
or0X
. You don't need to write any thing for decimal. See the code bellow.For more information visit tutorialspoint.
整数没有“前导零”,5 是 5,如果需要,您可以用前导 0 编写其字符串表示形式,因为您有 printf 修饰符。
Integers don't have "leading zeros" a 5 is a 5, you may write its string representation with leading 0 if you want, for that you have the printf modifiers.
在您的特定情况下,printf 会删除零。除了初始零之外,所有前导零都会被编译器删除,这会导致编译器将整数视为八进制。对于 005,八进制和十进制表示形式是相同的,不会打扰您,但除非您特别指的是八进制表示形式,否则它仍然会带来麻烦。
前导零纯粹与整数的字符串表示有关。要打印前导零,请使用“%03d”。这将确保字段长度为 3。
一般来说,“%d”将打印整数 x 个字符宽,并用前导空格填充。 “%0d”会做同样的事情,但会用前导零填充。
In your particular case, the zeroes are being dropped by printf.All leading zeroes are stripped out by the compiler except for the initial zero which causes your compiler to treat the integer as octal. For 005, both the octal and decimal representations are the same and should not bother you but still, it's asking for trouble unless you specifically meant the octal representation.
Leading zeroes have to do purely with the string representation of the integer. To print with leading zeroes, use "%03d". This will ensure a field length of 3.
In general, "%<x>d" will print an integer x characters wide and will pad with leading spaces. "%0<x>d" will do the same thing but will pad with leading zeroes.
背景
以“0”开头的数字以 8 为基数,即所谓的八进制数,使用数字 0-7。
正如以“0x”开头的数字是基于 16 的十六进制数字,使用数字 0-9 和 AF(不区分大小写,af)。
由于每个八进制数字代表 3 位,因此 027(9 位)可能用于代表 8 位,即一个字节。它的十进制值 = 0.8² + 2.81 + 7.8° = 23.
027 == 23 == 0x17
最后但并非最不重要的 028 会给出编译错误:不是一个有效的数字。
如今,十六进制数字无处不在,因为它们恰好将一个字节放入 2 个十六进制数字中。
然而,在旧的 Unix 时代,硬件也有其他 8 位的字。另请注意,在 Unix/Linux 中,用户、组和其他的文件权限形成 r/w/x 三元组,因此老派 0777 (所有权利)仍在使用中。
Background
Numbers starting with "0" are in base 8, so called octal numbers, using digits 0-7.
Just as numbers starting with "0x" are in base 16, hexadecimal numbers, using digits 0-9 and A-F (case insensitive, a-f).
As every octal digit represents 3 bits, 027 (9 bits) is probably used to represent 8 bits, a byte. Its decimal value = 0.8² + 2.8¹ + 7.8° = 23.
027 == 23 == 0x17
And last but not least 028 would give a compile error: not a valid number.
Nowadays hexadecimal numbers are ubiquitous, as they fit a byte into exactly 2 hex digits.
However in the old Unix time hardware had words other 8 bits too. Also note that in Unix/Linux file rights of user, group and others form a triplet of r/w/x, so old school 0777 (all rights) is still in use.