【问题标题】:Could initializing a static char array with a given size using a string literal of a different size cause undefined behavior?使用不同大小的字符串文字初始化具有给定大小的静态字符数组会导致未定义的行为吗?
【发布时间】:2016-01-25 19:03:44
【问题描述】:

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

static char foo[4] = "0";

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

static char bar[4] = "01234";

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

【问题讨论】:

  • C 中没有部分初始化。当你用声明赋值时,整个对象被初始化(无论是数组还是结构)。您未指定值的任何元素都将使用 0(如果是数字)或 NULL(如果是指针)初始化。 char 是数字类型,因此其余元素将设置为 0(即 '\0' 字符)。

标签: c arrays string undefined-behavior


【解决方案1】:

既然字符串比数组小,这还是定义好的吗?

是的,

static char foo[4] = "0";

定义明确。 foo 将包含 '0''\0''\0''\0'

sn-p

static char bar[4] = "01234";  

是违反约束的。而

static char bar[4] = "0123";  

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

char 数组的初始化字符串太长

【讨论】:

  • 你能澄清一下'foo'数组包含什么吗?我假设它会是 ['0'][NULL][garbage][garbage]?或者也许是 ['0'][NULL][NULL][NULL]?
  • @DeathTails;更新了答案。顺便说一句,NULL 是一个用于空指针的宏,而不是空字符串。
  • 不,在第二种情况下,您绝对会收到一条诊断消息,因为代码无效。这里没有“可能”。
  • @AnT 哎呀!现已更正。
【解决方案2】:

来自section 6.7.8.21 of the C99 standard

如果大括号括起来的列表中的初始值设定项比那里少 是聚合的元素或成员,或 用于初始化已知大小的数组的字符串文字 是数组中的元素,聚合的其余部分应为 隐式初始化与具有静态存储的对象相同 持续时间。

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

另外,从 6.7.8.32 开始:

声明

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

定义“普通”字符数组对象s和t,其元素用字符串初始化 文字。该声明与

相同
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };

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

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

总而言之,这两种情况都是明确定义的。

【讨论】:

  • 令人惊讶的是,另一个错误的答案与相同的错误。当初始化文字太长时,C 语言可以丢弃隐式终止 '\0' 字符。但是 C never 会丢弃任何明确指定的文字字符。 bar 的初始化是违反约束的。这是无效的。这就是标准中的示例旨在说明的内容。 char t[3] = "abc"; 是有效的 C,但 char t[3] = "abcd" 不是。后者是编译错误。与 OP 示例中的 bar 相同。
【解决方案3】:

第一个变种

static char foo[4] = "0";

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

第二种变体

static char bar[4] = "01234";

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

例如这仍然有效

static char bar[4] = "0123";

但不是你所拥有的。

记住

6.7.9 初始化
2任何初始化程序都不得尝试为未包含在正在初始化的实体中的对象提供值。
...
14 字符类型数组可以由字符串文字或 UTF-8 字符串文字初始化,可选用大括号括起来。字符串文字的连续字节(如果有空间或数组大小未知,则包括终止的空字符)初始化数组的元素。

【讨论】:

    猜你喜欢
    • 2021-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多