所以我有一组简单的代码:
#include int main() { char x[3] = "ABC"; // (*) puts(x); return 0; }
它返回一个奇怪的输出:
ABC-a
使用这个问题的最佳答案,我发现当我将x[3]
更改为x[4]
一切运行正常。
但为什么? 为什么我在x[3]
上得到一个奇怪的输出,为什么x[4]
很好?
既然你已经问过“为什么”这会产生ABC -a
,这里有一个解释:你的char x[3] = "ABC"
不适合puts
。 puts
期望一个字符串以零结尾。 但是,你的x
基本上是:
char x[3] = {'A', 'B', 'C'};
如您所知,没有办法获得(动态)数组的长度:
char * allocate(){ return malloc(rand() + 1); } char * mem = allocate(); // how large is mem??
你无法知道它有多长。 但是,要打印一个只是内存中连续字符序列的字符串,函数需要知道字符串(也就是字符序列)何时结束。
这就是美国信息交换标准码(ASCII)和许多其他字符集包含空字符的原因 。 它基本上是值为0
的char
:
char wrong_abc[3] = {'A', 'B', 'C'}; // when does it end? char correct_abc[4] = {'A', 'B', 'C', 0 }; // oh, there's a zero!
现在像puts
这样的函数可以简单地检查0
:
// Simplified, actual "puts" checks for errors and returns // EOF on error or a non-negative int on succes. void puts(const char * str){ int i = 0; while(str[i] != 0){ putchar(str[i]); i++; } putchar('n'); }
这就是你的原因
上面的puts
的实现永远不会找到0
并且意外地离开你拥有的内存(或访问其他数据),这通常会导致段错误或其他错误(或者更糟糕的是,长时间没有被检测到然后产生严重错误)。 在这种情况下的实际行为是不确定的。
请注意,字符串文字(例如"ABC"
)在结尾处自动具有' '
。 此外,编译器足够聪明,可以为您计算文字的长度,因此您可以简单地使用
char x[] = "ABC";
这样,您不必担心以后更改文字。
终止