以下代码不生成空终止符

/* 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/

10-11 22:12
查看更多