指针和malloc问题

And*_*ndy 3 c arrays malloc pointers

我对C很新,当他们引用字符串时我会遇到数组和指针.我可以要求输入2个数字(整数),然后返回我想要的那个(第一个数字或第二个数字),没有任何问题.但是,当我请求名称并尝试返回它们时,程序在输入第一个名称后崩溃并且不确定原因.

从理论上讲,我希望为名字保留内存,然后将其扩展为包含第二个名称.任何人都能解释为什么这会破裂

谢谢!

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



void main ()
{
    int NumItems = 0;

    NumItems += 1;
    char* NameList = malloc(sizeof(char[10])*NumItems);
    printf("Please enter name #1: \n");
    scanf("%9s", NameList[0]);
    fpurge(stdin);

    NumItems += 1;
    NameList = realloc(NameList,sizeof(char[10])*NumItems);
    printf("Please enter name #2: \n");
    scanf("%9s", NameList[1]);
    fpurge(stdin);

    printf("The first name is: %s",NameList[0]);
    printf("The second name is: %s",NameList[1]);

    return 0;

}
Run Code Online (Sandbox Code Playgroud)

tem*_*def 6

我认为您的问题在于此代码:

scanf("%9s", NameList[0]);
Run Code Online (Sandbox Code Playgroud)

这里的问题是scanf要求您提供的参数作为存储结果的位置必须是指针.如果你提供的东西不是一个指针,scanf就会把它看作是它,并且基本上将内存写入一个随机位置,从而导致程序崩溃.

解决这个问题需要两个步骤.首先,你要改变你的声明NameList,使它不再是一个char *.原因是a char *单个字符串,而您需要一个字符串数组.这将被定义为a char **,指向char *s 数组的指针.这可能如下所示:

char** NameList;
Run Code Online (Sandbox Code Playgroud)

接下来,您需要为字符串分配存储空间.这很棘手,有点微妙,因为你必须做两次分配.首先,您需要为数组本身分配空间,您可以这样做:

NameList = malloc (sizeof(char*) * NumItems);
Run Code Online (Sandbox Code Playgroud)

这会分配一个指向字符的指针数组,但它实际上并没有将这些指针中的指针设置为指向有效的内存位置.要解决这个问题,你需要遍历这个数组并将其所有元素设置为足够大的缓冲区指针来保存你的字符串 - 在这种情况下,长度为10的缓冲区:

int i;
for (i = 0; i < NumItems; ++i)
    NameList[i] = malloc (10); // Space for 10 characters
Run Code Online (Sandbox Code Playgroud)

现在,你可以打电话

scanf("%9s", NameList[0]);
Run Code Online (Sandbox Code Playgroud)

因为NameList[0]char *指向应该写入字符的缓冲区.

再一次评论你的代码 - 而不是分配一个元素的数组然后再将它重新分配给两个元素的数组,考虑只是预先分配所有空间.它更清楚一点.此外,由于您现在正在处理char *s 的缓冲区,每个缓冲区都需要初始化以指向其自己的缓冲区,如果您执行增量分配,则需要确保初始化char *分配给的所有新s.指向某处的缓冲区.如果你一步一步这样做,你很可能忘记设置指针并导致崩溃,而如果你预先做到这一点就没有这样的风险.

当需要释放动态分配的内存时,您需要反向运行分配过程,首先释放动态分配的字符串缓冲区,然后释放顶级缓冲区.例如:

for (i = 0; i < NumItems; ++i)
    free (NameList[i]);
free (NameList);
Run Code Online (Sandbox Code Playgroud)

这是必要的,因为free不能递归地工作.您需要显式释放所有分配的内存.

注意,你不能写这样的代码:

free (NameList);
for (i = 0; i < NumItems; ++i)
    free (NameList[i]);
Run Code Online (Sandbox Code Playgroud)

这将在运行时导致各种坏事,因为如果你先释放顶级数组,那么当你尝试迭代其内容释放指针时,你将会读取你不再拥有的内存.

希望这可以帮助!