访问 struct 中的 char 数组显示越界错误

Accessing char array inside struct showing out of bounds error

我有以下 C 结构并使用函数 getPerson(void) returns 一个指向我的结构的指针 returns 一个指向使用用户输入的新结构的指针。以下代码无法编译并出现以下错误:

     #include <stdio.h>  
     #include <stdlib.h>

     typedef struct {

         char name[50];
         int age;

     } person;

     person* getPerson(void) 
     {   
         person* newPerson = (person*)malloc(sizeof(person));
         int ageInput;
         char *nameInputPtr = (char*)malloc(50 * sizeof(char));

         printf("Please enter your name: \n");
         scanf("%s", nameInputPtr);
         printf("Please enter your age: \n");
         scanf("%d", &ageInput);

         newPerson->name[50] = *nameInputPtr;
         newPerson->age = ageInput;

         return newPerson;  
   }

我得到的错误:

struct.c:22:2: error: array index 50 is past the end of the array (which contains 50 elements)
  [-Werror,-Warray-bounds]
    newPerson->name[50] = *nameInputPtr;
    ^               ~~
struct.c:6:2: note: array 'name' declared here
    char name[50];
    ^

我设法通过第 22 行中的以下更改修复了我的错误:

22  newPerson->name[49] = *nameInputPtr;

所以我的更改是将第 50 号更改为第 6 行索引定义范围内的第 49 号。

因此,我不明白为什么第 6 行和第 22 行在我的原始代码中给出错误,我想对错误以及我的解决方案的清晰度和功能进行解释。

你必须使用sprintf

strcpy(newPerson->name, nameInputPtr);

注意 C 中的数组是基于 0 的, name[50] 不存在。

在您使用数组作为字符串的特定情况下,您必须验证数组的大小是否为 STR_LEN_MAX+1,因为字符串以 null 结尾。这意味着字符串中的最后一个字符后始终需要一个字节,其中可以插入 '[=16=]' 个字符。

C 中的数组索引基于 0。对于分配了 50 字节内存的数组,

 char name[50];

尝试使用 [50] 作为索引 off-by-one 并调用 undefined behaviour.

也就是说,

 newPerson->name[50] = *nameInputPtr;

不是您复制字符串的方式。你需要利用strcpy(),比如

strcpy(newPerson->name, nameInputPtr);

另外,在使用 scanf() 时限制输入字符串的长度是一个很好的做法,以避免可能的缓冲区溢出。变化

scanf("%s", nameInputPtr);

scanf("%49s", nameInputPtr);

但是,请记住,如果您的设计已经采用 固定大小 分配,那么使用动态内存就没有多大意义。您可以轻松地使用编译时分配的数组。

什么?

这个:

newPerson->name[50] = *nameInputPtr;

说 "assign the character at *nameInputPtr to the character at index 50 in name"。但是 name 只有 50 个字符长,并且数组在 C 中是从 0 开始的,所以这是越界的。

不过,该代码没有任何意义!你想要:

strcpy(newPerson->name, nameInputPtr);

复制整个字符串。但是,由于您不限制 scanf() 中的输入,因此存在传播缓冲区溢出的风险。

所以,更好,因为你已经有一个 person,只需输入它:

scanf("%49s", person->name);

记得检查 return 值。

当然你应该为年龄做同样的事情,不需要一个单独的整数然后复制到结构中。