使用不同大小的字符串文字初始化给定大小的静态字符数组会导致未定义的行为吗?

Could initializing a static char array with a given size using a string literal of a different size cause undefined behavior?

在我们的代码库中,我发现了类似于

的内容
static char foo[4] = "0";

既然字符串比数组小,这还是定义明确的吗?
假设,如果我有

static char bar[4] = "01234";

我假设数组将被初始化为“0123”。但这是由标准保证的还是另一种可能的未定义行为的情况?

Since the string is smaller than the array, is this still well-defined?

是的,

static char foo[4] = "0";

定义明确。 foo 将包含 '0''[=15=]''[=15=]''[=15=]'

片段

static char bar[4] = "01234";  

违反约束。而

static char bar[4] = "0123";  

定义明确,直到 bar 未作为 字符串 访问。在本例中,bar 是一个 char 数组,包含 4 个字符 '0''1''2''3'。对于后一种情况,您可能会收到警告

Initializer-string for char array is too long

来自section 6.7.8.21 of the C99 standard

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

具有静态存储持续时间的对象初始化为值 0。因此使用比数组短的字符串常量初始化固定大小的字符数组会导致剩余字节包含值 0。

此外,从 6.7.8.32 开始:

The declaration

char s[] = "abc", t[3] = "abc"; 

defines "plain" char array objects s and t whose elements are initialized with character string literals. This declaration is identical to

char s[] = { 'a', 'b', 'c', '[=11=]' },
t[] = { 'a', 'b', 'c' };

请注意,字符串常量中的额外字符(包括 NULL 终止符)在初始化数组时会被丢弃。

因此,对于您的示例中的 bar,它将包含字符 0123

所以总结一下,两种情况都是well-defined。

第一个变体

static char foo[4] = "0";

定义明确。整个数组被初始化。 foo[0] 设置为 '0',而数组的其余部分一直用整数零值(即 '[=15=]')填充到最后。

第二种变体

static char bar[4] = "01234";

是违反约束,即错误,无效代码。在 C 中,当您使用字符串文字初始化 char 数组时,您可以删除隐式终止 '[=15=]' 字符,但不能删除初始化程序中任何明确指定的字符。您不能使用长度为 5 的字符串文字来初始化长度为 4 的 char 数组。

例如这仍然有效

static char bar[4] = "0123";

但不是你所拥有的。

记得

6.7.9 Initialization
2 No initializer shall attempt to provide a value for an object not contained within the entity being initialized.
...
14 An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.