指针和malloc问题
我对 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;
}
I am fairly new to C and am getting stuck with arrays and pointers when they refer to strings. I can ask for input of 2 numbers (ints) and then return the one I want (first number or second number) without any issues. But when I request names and try to return them, the program crashes after I enter the first name and not sure why.
In theory I am looking to reserve memory for the first name, and then expand it to include a second name. Can anyone explain why this breaks?
Thanks!
#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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为您的问题出在这段代码中:
这里的问题是
scanf
要求您提供的作为存储结果的位置的参数必须是一个指针。如果您提供的内容不是指针,scanf
会将其视为指针,并且本质上会将内存写入随机位置,从而导致程序崩溃。解决这个问题需要两个步骤。首先,您需要更改
NameList
的声明,使其不再是char *
。原因是char *
是一个单个字符串,而您需要一个数组字符串。这将被定义为char **
,即指向char *
数组的指针。这可能看起来像这样:接下来,您需要为字符串分配存储空间。这很棘手并且有点微妙,因为您必须进行两次分配。首先,您需要为数组本身分配空间,您可以这样做:
这分配了一个指向字符的指针数组,但它实际上并未将这些数组中的指针设置为指向有效的内存位置。要解决此问题,您需要遍历该数组并将其所有元素设置为指向足以容纳字符串的缓冲区的指针 - 在本例中,长度为 10 的缓冲区:
现在,您可以调用
because
NameList[0]
是一个char *
,指向应写入字符的缓冲区。对代码的另一条评论 - 考虑预先分配所有空间,而不是分配一个元素的数组,然后将其重新分配给两个元素的数组。有点清楚了。另外,由于您现在正在处理 char * 的缓冲区,每个缓冲区都需要初始化以指向自己的缓冲区,因此如果您进行增量分配,则需要确保初始化您分配的所有新
char *
以指向某处的缓冲区。如果您一次执行此操作一步,那么您很可能会忘记设置指针并导致崩溃,而如果您预先执行此操作,则不会有这样的风险。当需要释放动态分配的内存时,您需要反向运行分配过程,首先释放字符串的动态分配的缓冲区,然后释放顶级缓冲区。例如:
这是必要的,因为
free
不能递归地工作。您需要显式释放您分配的所有内存。请注意,您不要编写这样的代码:
这将在运行时导致各种不好的事情,因为如果您首先释放顶级数组,那么当您尝试迭代其内容时会释放指针,您将读取不再拥有的内存。
希望这有帮助!
I think that your problem is in this code:
The problem here is that
scanf
requires that the argument you provide as a location to store the result must be a pointer. If you provide something that isn't a pointer,scanf
will treat it as though it is and essentially write memory to a random location, crashing the program.Fixing this requires two steps. First, you'll want to change your declaration of
NameList
so that it's no longer achar *
. The reason is that achar *
is a single string, whereas you want an array of strings. This would be defined as achar **
, a pointer to an array ofchar *
s. This might look like this:Next, you'll need to allocate storage space for the strings. This is tricky and a bit subtle because you have to do two allocations. First, you need to allocate space for the array itself, which you could do like this:
This allocates an array of pointers to characters, but it doesn't actually set up the pointers in those arrays to point to valid memory locations. To fix this, you'll want to then iterate across this array and set all of its elements to be pointers to buffers large enough to hold your strings - in this case, buffers of length 10:
Now, you can call
Because
NameList[0]
is achar *
pointing to the buffer into which the characters should be written.One more comment on your code - rather than allocating an array of one element and then reallocating it to an array of two elements later on, consider just allocating all the space up-front. It's a bit clearer. Also, since you're now dealing with a buffer of
char *
s, each of which needs to be initialized to point to its own buffer, if you do incremental allocations you'll need to be sure to initialize all of the newchar *
s you allocate to point to a buffer somewhere. If you do this one step at a time there's a good chance you'll forget to set up the pointers and cause a crash, whereas if you do it up front there's no such risk.When it comes time to free the dynamically-allocated memory, you'll need to run the allocation process in reverse, first freeing the dynamically-allocated buffers for the strings, then freeing the top-level buffer. For example:
This is necessary because
free
doesn't work recursively. You need to explicitly deallocate all the memory that you allocate.Note that you do not write the code like this:
This will cause all sorts of Bad Things at runtime because if you free the top-level array first, then as you try iterating over its contents freeing the pointers, you'll be reading memory that you no longer own.
Hope this helps!
您的 NameList 变量是一个 char *,它是指向单个字符串的指针。 (char 是单个字符,char * 是单个字符串,char ** 是字符串数组。)
当您使用 NameList[1] 时,您实际上是在索引字符串的第二个字符,不是第二个字符串本身。
您应该分配一个字符串数组,如下所示:
编辑:修复了一些编译错误。 (示例代码。) 请注意,sizeof(char) 并不是真正需要的,因为它总是 1。很高兴但要明确。
Your NameList variable is a char *, which is a pointer to a single string. (char is a single character, char * is a single string, char ** is an array of strings.)
When you use NameList[ 1], you are actually indexing the second character of the string, not the second string itself.
You should instead allocate an array of strings, something like this:
Edit: Fixed some compile errors. (Sample code.) Note that the sizeof(char) isn't really needed, as it's always 1. Nice to be explicit, though.
如果您需要一个 char 的二维数组(其中每个元素都是 char 的数组),那么您正在以错误的方式分配内存。正确的方法是:
If you need a 2d array of chars (an array in which every element is an array of char s), you are allocating memory in the wrong way. Correct way would be:
还可以考虑仅使用堆栈空间,而不是使用
malloc
和动态分配堆空间:通常,除非您需要动态调整大小的数组,否则使用普通数组要容易得多。
Also consider just using stack space instead of using
malloc
and dynamically allocating heap space:Generally, unless you have a need for dynamically sized arrays, it's much much easier to use plain arrays.