数组末尾显示随机字符

时间:2018-07-25 16:14:52

标签: c arrays printf

在我刚开始学习语言时,我想用C上的数组测试事物。这是我的代码:

#include <stdio.h>
main(){
  int i,t;
  char orig[5];
  for(i=0;i<=4;i++){
    orig[i] = '.';
  }

  printf("%s\n", orig);
}

这是我的输出:

.....�

就是这样。那些神秘人物是什么?我做错了什么?

5 个答案:

答案 0 :(得分:7)

带有%s

printf()需要一个指向 string 的指针,即,指向以空终止的字符数组的初始元素的指针。您的数组不是以null结尾的。

因此,printf()在搜索终止的空字符时超出范围,随后调用undefined behavior

如果要将其用作 string ,则必须对数组进行空终止。

语录:C11,第§7.21.6.1章,(强调我的

  

s

     

如果不存在l长度修饰符,则参数应为指向字符类型数组的初始元素的指针。 280)数组中的字符为   写入(但不包括)终止空字符。如果   指定了精度,但写入的字节数不超过该字节数。 如果   没有指定精度或大于数组的大小,数组应   包含空字符。

快速解决方案:

  • 将数组大小增加1,char orig[6];
  • 最后添加一个空终止符。在循环主体之后,添加orig[i] = '\0';

然后打印结果。

答案 1 :(得分:4)

char orig[5];//creates an array of 5 char.  (with indices ranging from 0 to 4)

|?|?|?|0|0|0|0|0|?|?|?|?|
      |         ^memory you do not own (your mysterious characters)
      ^start of orig

for(i=0;i<=4;i++){  //attempts to populate array with '.'
    orig[i] = '.';

|?|?|?|.|.|.|.|.|?|?|?|?|
      |         ^memory you do not own (your mysterious characters)
      ^start of orig

这将导致一个非null终止的char数组,如果在需要C字符串的函数中使用该数组,它将调用未定义的行为。 C字符串必须包含足够的空间以允许空终止。将您的声明更改为以下内容。

char orig[6];

然后将空终止符添加到循环的末尾:

  ...
  for(i=0;i<=4;i++){
    orig[i] = '.';
  }
  orig[i] = 0;

结果:

|?|?|?|.|.|.|.|.|0|?|?|?|
      |           ^memory you do not own
      ^start of orig

注意:因为空终止符会导致C字符串,所以使用它的函数知道如何解释其内容(即没有未定义的行为),并且您的神秘人物被拒之门外。 >

答案 2 :(得分:2)

数组和字符数组之间有区别。您可以认为字符数组是数组的一种特殊情况,其中每个元素在C中的类型为char,并且该数组应以字符nullASCII value 0)结尾(终止)

带有%s

printf()格式说明符期望一个指向以null字符结尾的字符数组的指针。您的数组不是以null结尾的数组,因此printf函数超出了您分配的5个字符,并打印出第5个字符('。')后出现的垃圾值。

要解决您的问题,您需要静态分配大小大于要存储的字符的字符数组。在您的情况下,可以使用大小为6的字符数组。

#include <stdio.h>
int main(){
  int i,t;
  char orig[6]; // If you want to store 5 characters, allocate an array of size 6 to store null character at last position.

  for (i=0; i<=4; i++) {
    orig[i] = '.';
  }

  orig[5] = '\0';

  printf("%s\n", orig);
}

有理由为空字符浪费一个额外的字符空间。原因是每当您将任何数组传递给函数时,只有第一个元素的指针才传递给函数(在函数堆栈中推送)。这使得函数无法确定数组的末尾(意味着sizeof之类的运算符将无法在函数内部运行,而sizeof将返回计算机中指针的大小)。这就是原因,memcpymemset之类的函数需要一个附加的函数参数,该参数提及数组大小(或要操作的长度)。

但是,使用字符数组,函数可以通过查找特殊字符(null字符)来确定数组的大小。

答案 3 :(得分:1)

您需要在字符串的末尾添加一个NUL字符(\0)。

#include <stdio.h>

main()
{
  int  i,t;
  char orig[6];

  for(i=0;i<=4;i++){
    orig[i] = '.';
  }

  orig[i] = '\0';
  printf("%s\n", orig);
}

如果您不知道\0是什么,我强烈建议您检查ascii表(https://www.asciitable.com/)。

祝你好运

答案 4 :(得分:1)

prinftf获取任何内存位置的起始指针,在这种情况下为数组并打印直到遇到\0字符。这些类型的字符串称为null终止的字符串。

因此,请在末尾添加\0并输入直到(array-2的大小)这样的字符:

main(){
  int i,t;
  char orig[5];
  for(i=0;i<4;i++){ //less then size of array -1
    orig[i] = '.';
  }
  orig[i] = '\0'
  printf("%s\n", orig);
}