Arrays 什么';字符数组中的尾随符号是什么?该数组是用括号括起来的列表在clang中初始化的? #包括 int main(int argc,const char*argv[]{ 字符名称1[]={'f','o','o'}; 字符名称2[]=“foo”; printf(“%s\n”,名称1); printf(“%s\n”,名称2); 返回0; }
运行上述代码将导致:Arrays 什么';字符数组中的尾随符号是什么?该数组是用括号括起来的列表在clang中初始化的? #包括 int main(int argc,const char*argv[]{ 字符名称1[]={'f','o','o'}; 字符名称2[]=“foo”; printf(“%s\n”,名称1); printf(“%s\n”,名称2); 返回0; },arrays,c,Arrays,C,运行上述代码将导致: foox\363\277\357\376 foo Program ended with exit code: 0 那么,这两个初始值设定项之间有什么区别呢?name1是一个由三个字符组成的数组{f',o',o'} name2是由四个{f',o',o','\0'}字符组成的数组 printf(“%s”,…)需要一个以空字符结尾的数组。因为name1不是,所以开始取消引用数组末尾之后的字符,这可能具有传统的未定义行为。数组中没有尾随符号 但是printf的%s格式需要一个字符
foox\363\277\357\376
foo
Program ended with exit code: 0
那么,这两个初始值设定项之间有什么区别呢?
name1
是一个由三个字符组成的数组{f',o',o'}
name2
是由四个{f',o',o','\0'}
字符组成的数组
printf(“%s”,…)
需要一个以空字符结尾的数组。因为name1
不是,所以开始取消引用数组末尾之后的字符,这可能具有传统的未定义行为。数组中没有尾随符号
但是printf
的%s
格式需要一个字符串,而数组name1
不是字符串:根据定义,C字符串以零结尾……而数组不是。因此行为是未定义的,在您的特定情况下,printf
继续打印内存中恰好位于name1
内容后面的随机值,第一个数组(即{f','o','o'}
)将不具有null
字符'\0'
,第二个(即,“foo”
)将显示在哪里
使用%s
时的规范说明如下:
如果不存在l修饰符:const char*参数应为
是指向字符类型数组的指针(指向字符串的指针)。
数组中的字符最多写入(但不包括)一个
终止空字节('\0');如果指定了精度,则不再指定
写入的数值大于指定的数值。如果给定精度,则不
空字节需要存在;如果未指定精度,或
大于数组的大小,数组必须包含
终止空字节
由于您的printf
没有包含精度,它将从数组中写入字符,直到达到空字节('\0'
)。因此,在charname1[]={'f','o','o'}的情况下代码>导致从分配给name1数组的内存中输出printf写入字符。这种行为被认为是未定义的
这就是为什么printf(“%s\n”,name1)
打印foo加上内存中不应该访问的下一个位置的一些额外符号,而使用printf(“%s\n”,name2)
它精确地打印字符串“foo”
。在C语言中,如果使用逐字符初始值设定项初始化字符串,则需要放入'\0'
,该字符串为空/终止字符以指示字符串的结束。
所以name1应该是{'f','o','o','0'}
x\363\277\357\376
您可以在输出末尾看到的只是垃圾值,这是因为printf在字符串名称1的末尾找不到“\0”而打印出来的
对于name2,您使用双引号初始化字符串,该字符串会自动在字符串末尾添加一个'\0'