我以多个问题here之一问过这个问题。但是人们要我分开问他们。那么为什么要问这个问题。
请考虑以下code lines:
char a[5] = "geeks"; //1
char a3[] = {'g','e','e','k','s'}; //d
printf("a:%s,%u\n",a,sizeof(a)); //5
printf("a3:%s,%u\n",a3,sizeof(a3)); //j
printf("a[5]:%d,%c\n",a[5],a[5]);
printf("a3[5]:%d,%c\n",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的内容?我觉得确实在第1行中添加了\ 0,但在printof中却没有考虑它的sizeof。我对吗?
很抱歉再次提出第二个问题。
答案 0 :(得分:2)
char a[5] = "geeks"; //1
在这里,您将数组的大小指定为“ 5”,并使用5个字符对其进行初始化。 因此,您没有“ C字符串”,根据定义,该字符串以NUL结尾。 (0)。
printf("a:%s,%u\n",a,sizeof(a)); //5
数组本身的大小仍然为5,由sizeof运算符正确报告,但是您对printf的调用是未定义的行为,并且可以在错误内容之后打印任何内容-它只会继续查看下一个地址,直到它到达为止在某个地方找到0。那可能是立即的,或者可能会打印出1000000个垃圾字符,或者可能导致某种形式的段错误或其他崩溃。
char a3[] = {'g','e','e','k','s'}; //d
由于您没有指定数组的大小,因此编译器将通过初始化语法来确定数组的大小。但是,您选择初始化a3的方式仍将仅提供5个字节的长度。 这样做的原因是您的初始化只是一个初始化列表,而不是“字符串” 。因此,您随后对printf的调用也是不确定的行为,很幸运,在您的情况下,位置a3 [5]似乎为0。
有效地,两个示例都具有相同的错误。
您可能因此有所不同:
char a3[] = "geeks";
使用字符串文字来初始化大小未指定的数组将导致编译器分配足够的内存来容纳字符串和附加的NUL终止符,并且sizeof(a3)现在将产生6
答案 1 :(得分:1)
“怪胎”是C语言中的字符串文字。
定义“怪胎”时,编译器会自动将NULL字符添加到末尾。这使它长6个字符。
但是您正在将其分配给char a[5]
。 这将导致不确定的行为。
如@DavidBowling所述,在这种情况下,适用以下条件
(第6.7.8.14节)C99标准。
可由字符串文字初始化字符类型的数组,可以选择将其括在大括号中。字符串文字的连续字符(如果有空间或数组大小未知,则包括终止的空字符)将初始化数组的元素
元素“怪胎”将被复制到数组“ a”中,但不会复制NULL字符。
因此,在这种情况下,当您尝试打印阵列时,它将继续打印直到遇到内存中的\0
。
从其他打印语句中可以看到a[5]
的值为V
。大概系统上的下一个字节是\0
,数组打印停止。
因此,在系统中在这种情况下,将打印"geeksV"
。