为什么对于长度为k的字符串,我需要char [k + 1]而不是char [k]?

时间:2015-12-29 21:55:24

标签: c output

所以我有一套简单的代码:

#include <stdio.h>

int main()
{
  char x[3] = "ABC"; // (*)
  puts(x);
  return 0;
}

它返回一个奇怪的输出:

ABC¬ a

使用this question的热门答案,我发现当我将x[3]更改为x[4]时,一切运行正常。

但为什么呢?为什么我在x[3]上得到一个奇怪的输出,为什么x[4]很好?

5 个答案:

答案 0 :(得分:7)

终止\0没有空间。事实上,我希望编译在这种情况下失败。

尝试

char x[4] = "ABC";

或者,如 @Zeta 所示,只需

char x[] = "ABC";

答案 1 :(得分:4)

您的字符串应终止 \0

使用

char x[] = "ABC";

代替。

  

使用这个问题的最佳答案,我发现当我改变时   x [3]到x [4]一切运行正常。

     

但是为什么? x [3]发生了什么,给出了如此奇怪的输出?

puts()一直持续到遇到终止\0 字节为止。因此,如果您不在字符串的末尾提供一个字符串,它会一直在字符串后面运行,直到找到\0崩溃 ..

请参阅puts() description

  

该函数从指定的地址(str)开始复制,直到它   到达终止空字符('\ 0')。这终止了   null-character不会复制到流中。

答案 2 :(得分:4)

字符串由空字符终止 - 您尚未为其分配空间。

待办事项

char x[] = "ABC";

让编译器为你完成工作!

答案 3 :(得分:4)

因为您已经问过&#34;为什么&#34;这会产生ABC -a,这里有一个解释:您的char x[3] = "ABC"并不适合putsputs期望字符串以零结尾。但是,您的x基本上是:

char x[3] = {'A', 'B', 'C'};

如您所知,没有办法获得(动态)数组的长度:

char * allocate(){
   return malloc(rand() + 1);
}

char * mem = allocate(); // how large is mem??

你无法知道它有多久。但是,要打印一个只是内存中连续字符序列的字符串,函数需要知道字符串(也就是字符序列)何时结束。

这就是American Standard Code for Information Interchange (ASCII)和许多其他字符集包含null character的原因。它基本上是char,其值为0

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');
}

这就是你

的原因
  • 需要字符序列+1,
  • 中所有字符的内存
  • 忘记0
  • 时会出现未定义的行为

上面的puts的实现永远不会找到0并且意外地离开您拥有的内存(或访问其他数据),这通常会导致段错误或其他错误(或者更糟糕的是,不会; t长时间检测到然后产生严重错误)。在这种情况下的实际行为是不确定的。

请注意,字符串文字(例如"ABC")最后会自动生成'\0'。此外,编译器足够聪明,可以为您计算文字的长度,因此您只需使用

即可
char x[] = "ABC";

这样,如果您以后更改文字,就不必担心。

答案 4 :(得分:0)

每当你声明一个字符串变量时,只需要为结束字符'\0'添加一个字符,你就可以了。