使用较小的字符串文字初始化char数组

sid*_*yll 12 c string initialization

如果我写:

char arr[8] = "abc";
Run Code Online (Sandbox Code Playgroud)

什么arr[4]可能是什么规格?我用Clang做了一些测试,似乎数组中剩余的字符都设置为null.此外,char arr[8] = "";每个字节都为零.不确定这是编译器的便利性,标准行为,纯粹的巧合还是我弄错了.


void a()
{
    char arr[8] = "abc";    /* breakpoint here, line 3 */
    strcpy(arr, "1234567");
}
int main()
{
    a();
    a();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

调试器脚本:

Breakpoint 1, a () at str.c:3
3           char arr[8] = "abc";
(gdb) s
Current language:  auto; currently minimal
4           strcpy(arr, "1234567");
(gdb) p arr
$1 = "abc\000\000\000\000"
(gdb) c      
Continuing.

Breakpoint 1, a () at str.c:3
3           char arr[8] = "abc";
(gdb) p arr
$2 = "1234567"
(gdb) s
4           strcpy(arr, "1234567");
(gdb) p arr
$3 = "abc\000\000\000\000"

und*_*gor 16

这是标准行为.

arr[3] 初始化为0,因为终止0是字符串文字的一部分.

所有剩余的元素也被初始化为0 - ISO/IEC 9899: 1999,6.7.8,21:

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

char与静态存储的对象初始化为0.


Lun*_*din 7

char arr[8] = "abc";
Run Code Online (Sandbox Code Playgroud)

完全等同于

char arr[8] = {'a', 'b', 'c', '\0'};
Run Code Online (Sandbox Code Playgroud)

ISO C6.7.8§21规定

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

简单来说,这意味着数组末尾的所有值都将设置为0.因此标准保证您的代码等效于:

char arr[8] = {'a', 'b', 'c', '\0', 0, 0, 0, 0};
Run Code Online (Sandbox Code Playgroud)

当然,'\ 0'恰好也是零值.

此规则对所有数组都是通用的,而不仅仅是字符串.此外,同样适用于初始化结构但仅显式设置其少数成员(6.7.8§18).


这就是你可以写代码的原因

char arr[8] = "";
Run Code Online (Sandbox Code Playgroud)

在此示例中,数组的第一个元素初始化为'\ 0',其余项隐式为零.编译器将其转换为

char arr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Run Code Online (Sandbox Code Playgroud)

  • @КонстантинВан 对于后代:它意味着全局变量或定义的静态变量(文件静态或函数静态)。这些对象是在程序启动之前创建的;启动代码包含“清零”这些对象的命令。这意味着所有指针都是空指针,所有数字都为零,所有字符数组都有零字节,因此 strlen(arr) 返回 0。这实际上是可取的;对于具有“自动存储持续时间”(局部变量)的对象不执行此操作的原因是,每次传递代码时都会发生这种情况,而不是静态变量只发生一次。 (2认同)