以下代码不生成空终止符
/* Case 1 */
#include <stdio.h>
void main () {
char wbuf[16] = "0123456789abcdef";
printf("%s\n", wbuf);
}
参见拆卸总成的相关部分
0x4005b4 <main+23>: movabs $0x3736353433323130,%rax
0x4005be <main+33>: mov %rax,-0x20(%rbp)
0x4005c2 <main+37>: movabs $0x6665646362613938,%rax
0x4005cc <main+47>: mov %rax,-0x18(%rbp)
0x4005d0 <main+51>: lea -0x20(%rbp),%rax --->prinft related
0x4005d4 <main+55>: mov %rax,%rdi
0x4005d7 <main+58>: callq 0x400470 <puts@plt>
而下面的代码生成一个:
/* Case 2 */
#include <stdio.h>
void main () {
char wbuf[17] = "0123456789abcdef";
printf("%s\n", wbuf);
}
再次查看dis组件的相关部分
0x4005b4 <main+23>: movabs $0x3736353433323130,%rax
0x4005be <main+33>: mov %rax,-0x20(%rbp)
0x4005c2 <main+37>: movabs $0x6665646362613938,%rax
0x4005cc <main+47>: mov %rax,-0x18(%rbp)
0x4005d0 <main+51>: movb $0x0,-0x10(%rbp) >>>>>> Null terminator comes here
0x4005d4 <main+55>: lea -0x20(%rbp),%rax --->prinft related
0x4005d8 <main+59>: mov %rax,%rdi
0x4005db <main+62>: callq 0x400470 <puts@plt>
我假设字符串初始化为
char wbuf[xxx] = "yyyy"
来添加一个空终止符,就像第二种情况一样。然而,以下问题仍然存在:为什么编译器在第一种情况下不警告“初始化时间过长”
而不是默默地避开空终止符。还有一个类似于
char wbuf[16] = "0123456789abcdef\0"
的字符触发警告:字符数组的初始值设定项字符串太长。这种行为会在编译器中改变吗。我在用gcc
ubuntu和正在使用O0选项编译
为什么它在1和2中的行为不一致,例如
在case1中盲目地写在16之后并添加了空终止符?
`
最佳答案
从关于初始化的C11 standard第6.7.9节(emphasis mine):
字符类型的数组可以由字符串初始化
literal或UTF-8字符串literal,可选地括在大括号中。
字符串文本的连续字节(包括终止的空值
字符(如果有空间或数组大小未知)
初始化数组的元素。
所以编译器完全符合规范。
关于c - 是什么解释了C.w.r.t字符串初始化的编译器的这种行为?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41028752/