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.
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)