3

当我刚刚开始学习这门语言时,我想用 C 上的数组来测试一下。这是我的代码:

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

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

这是我的输出:

.....�

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

4

5 回答 5

7

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

因此,在搜索终止的空字符时,printf()会越界,随后会调用未定义的行为

如果您希望将其用作字符串,则必须以空值终止您的数组。

引用:C11,第 7.21.6.1 章,(强调我的

s

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

快速解决方案:

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

然后,打印结果。

于 2018-07-25T16:17:08.467 回答
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

这会产生一个非空终止的 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 字符串,使用它的函数知道如何解释其内容(即没有未定义的行为),并且您的神秘字符被搁置了。

于 2018-07-25T16:25:35.390 回答
2

数组和字符数组是有区别的。您可以认为字符数组是数组的一种特殊情况,其中每个元素都是charC 中的类型,并且该数组应以字符null( ) 结束(终止ASCII value 0)。

%s格式说明符printf()需要一个指向以字符结尾的字符数组的指针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会返回机器中指针的大小)。这就是原因,类似的函数memcpy需要memset一个额外的函数参数,其中提到了数组大小(或您想要操作的长度)。

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

于 2018-07-25T16:34:22.917 回答
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/)。

祝你好运

于 2018-07-25T16:17:43.207 回答
1

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

所以请\0在末尾添加 a 并输入字符直到(数组大小 - 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);
}
于 2018-07-25T16:25:44.710 回答