我把这个问题作为这里的多个问题之一提出。但人们要求我单独问他们。那么为什么要问这个问题呢。
考虑以下代码行:
char a[5] = "geeks"; //1
char a3[] = {'g','e','e','k','s'}; //d
printf("a:%s,%un",a,sizeof(a)); //5
printf("a3:%s,%un",a3,sizeof(a3)); //j
printf("a[5]:%d,%cn",a[5],a[5]);
printf("a3[5]:%d,%cn",a3[5],a3[5]);
输出:
a:geeksV,5
a3:geeks,5
a[5]:86,V
a3[5]:127,
然而,最初的问题是:
a:geeks,5
a3:geeksV,5
原问题中的问题1是:
- 第1行是否添加\0?请注意,sizeof在第5行打印5,表示\0不在。但是,#5怎么不会像#j行那样打印类似geeksU的东西呢?我觉得\0确实被添加到了第1行,但在sizeof中没有被考虑,而在printf中被考虑。我说得对吗
再次抱歉问了第二个问题。
char a[5] = "geeks"; //1
在这里,您将数组的大小指定为"5",并用5个字符对其进行初始化。因此,您没有一个"C字符串",根据定义,它以NUL结束。(0(。
printf("a:%s,%un",a,sizeof(a)); //5
数组本身的大小仍然是5,sizeof运算符正确地报告了这一点,但您对printf的调用是未定义的行为,可以在arrray的内容之后打印任何内容——它只会继续查看下一个地址,直到在某个地方找到0。这可能是立即的,也可能打印1000000个垃圾字符,也可能导致某种segfault或其他崩溃。
char a3[] = {'g','e','e','k','s'}; //d
因为没有指定数组的大小,所以编译器将通过初始化语法来确定数组的大小。然而,按照您选择的初始化a3的方式,它仍然只提供5个字节的长度。原因是您的初始化只是一个初始化列表,而不是一个"字符串">。因此,您随后对printf的调用也是未定义的行为,幸运的是,在位置a3[5],您的情况下似乎有一个0。
实际上,这两个例子都有相同的错误。
你可以有不同的这样:
char a3[] = "geeks";
使用字符串文字初始化未指定大小的数组将导致编译器分配足够的内存来容纳字符串和附加的NUL终止符,sizeof(a3(现在将产生6。
"geeks"这里是C.中的字符串文字
当您定义"极客"时,编译器会自动在末尾添加NULL字符。这使得它有6个字符长。
但您正在将其分配给char a[5]
这将导致未定义的行为
如@DavidBowling所述,在这种情况下,以下条件适用
(第6.7.8.14节(C99标准。
字符类型的数组可以由字符串文字初始化,也可以用大括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,则包括终止空字符(初始化数组的元素
元素"geeks"将被复制到数组"a"中,但NULL字符不会被复制。
因此,在这种情况下,当您尝试打印数组时,它将继续打印,直到在内存中遇到