字符串常量超过数组大小时没有错误



我尝试了下面的代码,预期会出现编译警告或错误,因为一个字符串是用内存中的nul字符完成的,代码已经编译并且字符串打印正确。如果我在初始化中添加一个新字符,我会收到一个编译警告。请澄清一下?谢谢

#include <stdio.h>
int main () {
char greeting[6] ="123456";
printf("Greeting message: %sn", greeting );
return 0;
}

初始化是合法的。根据C17标准(N2176草案(6.7.9(14(:

字符类型的数组可以由字符串文字或UTF–8字符串文字初始化,可选地封闭在大括号中。字符串文字的连续字节(包括终止的null字符如果有空间或如果数组大小未知(初始化数组的元素。

因此,当您编写代码时,假设您确实想要6个字符的{'1', '2', '3', '4', '5', '6'},并且没有终止null。如果您不是真的要将数组用作字符串,而是想要一种更简洁的方法来初始化它,那么这有时是有用的

(当然,随后尝试将greeting传递给printf,就好像它是null终止的一样,这是而不是合法的C;这是未定义的行为。如果它看起来有效,那只是偶然的,很可能当时内存中的下一个字节恰好是0。(

如果你想确定包括空字节,你可以写

char greeting[6] ="123456";

这是一个警告。或者,当然,你可以让编译器为你计算出数组的大小,然后只写

char greeting[] = "123456";

在这种情况下,保证了终止null,并且数组的大小为7。

如果数组的大小已知,它可能比字符串文字的大小小一个,在这种情况下,终止的null字符将被忽略。

char greeting[7] ="123456";生成数组{'1','2','3','4','5','6',0}。注意后面的空字节。

char greeting[6] ="123456";生成数组{'1','2','3','4','5','6'},没有空字节。

printf("Greeting message: %sn", greeting );恰好工作,因为下面的内存恰好为零。它可以是任何东西。

下面是一个例子,在我的特定例子中,它说明了这个问题。

#include <stdio.h>
int main () {
char foo[] = "abcd";
char greeting[4] ="1234";
printf("foo = %p, greeting = %pn", foo, greeting);
printf("%sn", greeting);
return 0;
}

输出是…

foo = 0x7ffee6c37427, greeting = 0x7ffee6c37423
1234abcd

在这里,我们看到foo在紧接着greeting的存储器中。当printf读取greeting时,它尽职尽责地读取直到位于foo末尾的第一个空字节。

greeting
|
v
1234abcd
^
|
foo

因此,除非您真的需要分配比初始化字符串更多的内存,否则请使用greeting[] = "123456"来确保您有一个空字节。

相关内容

最新更新