C语言 对数组使用动态内存分配
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4641476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Dynamic Memory allocation for arrays
提问by Rafay
How am I supposed to use dynamic memory allocations for arrays?
我应该如何为数组使用动态内存分配?
For example here is the following array in which i read individual words from a .txt file and save them word by word in the array:
例如,这里是以下数组,我从 .txt 文件中读取单个单词并将它们逐字保存在数组中:
Code:
代码:
char words[1000][15];
Here 1000 defines the number of words the array can save and each word may comprise of not more than 15 characters.
这里 1000 定义了数组可以保存的单词数,每个单词可以包含不超过 15 个字符。
Now I want that that program should dynamically allocate the memory for the number of words it counts. For example, a .txt file may contain words greater that 1000. Now I want that the program should count the number of words and allocate the memory accordingly.
现在我希望该程序应该为它计数的字数动态分配内存。例如,一个 .txt 文件可能包含大于 1000 的单词。现在我希望程序应该计算单词的数量并相应地分配内存。
Since we cannot use a variable in place of [1000], I am completely blank at how to implement my logic. Please help me in this regard.
由于我们不能使用变量代替 [1000],因此我对如何实现我的逻辑一无所知。请在这方面帮助我。
回答by
You use pointers.
你使用指针。
Specifically, you use a pointer to an address, and using a standard c library function calls, you ask the operating system to expand the heap to allow you to store what you need to.
具体来说,您使用指向地址的指针,并使用标准的 c 库函数调用,您要求操作系统扩展堆以允许您存储您需要的内容。
Now, it might refuse, which you will need to handle.
现在,它可能会拒绝,您需要处理。
The next question becomes - how do you ask for a 2D array? Well, you ask for an array of pointers, and then expand each pointer.
下一个问题变成了 - 你如何要求一个二维数组?好吧,您需要一个指针数组,然后展开每个指针。
As an example, consider this:
作为一个例子,考虑这个:
int i = 0;
char** words;
words = malloc((num_words)*sizeof(char*));
if ( words == NULL )
{
/* we have a problem */
printf("Error: out of memory.\n");
return;
}
for ( i=0; i<num_words; i++ )
{
words[i] = malloc((word_size+1)*sizeof(char));
if ( words[i] == NULL )
{
/* problem */
break;
}
}
if ( i != num_words )
{
/* it didn't allocate */
}
This gets you a two-dimensional array, where each element words[i]can have a different size, determinable at run time, just as the number of words is.
这为您提供了一个二维数组,其中每个元素words[i]可以具有不同的大小,可以在运行时确定,就像单词的数量一样。
You will need to free()all of the resultant memory by looping over the array when you're done with it:
完成后,您将需要free()通过循环遍历数组来获得所有结果内存:
for ( i = 0; i < num_words; i++ )
{
free(words[i]);
}
free(words);
If you don't, you'll create a memory leak.
如果不这样做,则会造成内存泄漏。
You could also use calloc. The difference is in calling convention and effect - callocinitialises all the memory to 0whereas mallocdoes not.
您也可以使用calloc. 区别在于调用约定和效果 -calloc将所有内存初始化为,0而malloc不会。
If you need to resize at runtime, use realloc.
如果您需要在运行时调整大小,请使用realloc.
Also, important, watch out for the word_size+1that I have used. Strings in C are zero-terminated and this takes an extra character which you need to account for. To ensure I remember this, I usually set the size of the variable word_sizeto whatever the size of the word should be (the length of the string as I expect) and explicitly leave the +1 in the malloc for the zero. Then I know that the allocated buffer can take a string of word_sizecharacters. Not doing this is also fine - I just do it because I like to explicitly account for the zero in an obvious way.
另外,重要的是,请注意我使用的 word_size+1。C 中的字符串以零结尾,这需要您考虑一个额外的字符。为了确保我记住这一点,我通常将变量word_size的大小设置为单词的大小(我期望的字符串长度),并明确地将 malloc 中的 +1 保留为零。然后我知道分配的缓冲区可以接受一串word_size字符。不这样做也很好——我这样做是因为我喜欢以一种明显的方式明确地解释零。
There is also a downside to this approach- I've explicitly seen this as a shipped bug recently. Notice I wrote (word_size+1)*sizeof(type)- imagine however that I had written word_size*sizeof(type)+1. For sizeof(type)=1these are the same thing but Windows uses wchar_tvery frequently - and in this case you'll reserve one byte for your last zero rather than two - and they are zero-terminated elements of type type, not single zero bytes. This means you'll overrun on read and write.
这种方法也有一个缺点——我最近明确地将其视为一个附带的错误。请注意我写的(word_size+1)*sizeof(type)- 想象一下,我已经写了word_size*sizeof(type)+1。因为sizeof(type)=1这些是相同的东西,但 Windows 使用wchar_t非常频繁 - 在这种情况下,您将为最后一个零保留一个字节而不是两个 - 它们是 type 的零终止元素type,而不是单个零字节。这意味着您将在读写上超支。
Addendum: do it whichever way you like, just watch out for those zero terminators if you're going to pass the buffer to something that relies on them.
附录:以您喜欢的方式进行操作,如果您要将缓冲区传递给依赖它们的东西,请注意那些零终止符。
回答by Heatsink
While Ninefingers provided an answer using an array of pointers , you can also use an array of arrays as long as the inner array's size is a constant expression. The code for this is simpler.
虽然 Ninefingers使用指针数组提供了答案,但您也可以使用数组数组,只要内部数组的大小是一个常量表达式。用于此的代码更简单。
char (*words)[15]; // 'words' is pointer to char[15]
words = malloc (num_words * sizeof(char[15]);
// to access character i of word w
words[w][i];
free(words);
回答by anatolyg
If the 15in your example is variable, use one of the available answers (from Ninefingers or John Boker or Muggen).
If the 1000is variable, use realloc:
如果15示例中的 是可变的,请使用可用答案之一(来自 Ninefingers 或 John Boker 或 Muggen)。如果1000是变量,请使用realloc:
words = malloc(1000 * sizeof(char*));
// ... read 1000 words
if (++num_words > 1000)
{
char** more_words = realloc(words, 2000 * sizeof(char*));
if (more_words) {printf("Too bad");}
else {words = more_words;}
}
In my code above, the constant 2000is a simplification; you should add another variable capacityto support more than 2000 words:
在我上面的代码中,常量2000是一种简化;您应该添加另一个变量capacity以支持超过 2000 个单词:
if (++num_words > capacity)
{
// ... realloc
++capacity; // will reallocate 1000+ words each time; will be very slow
// capacity += 1000; // less reallocations, some memory wasted
// capacity *= 2; // less reallocations but more memory wasted
}
回答by Mahesh
If you intend to go for C++, STL is very useful for something dynamic allocation and is very easy. You can use std::vector ..
如果您打算使用 C++,STL 对于动态分配非常有用,而且非常简单。您可以使用 std::vector ..
回答by John Bode
If you're working in C:
如果你在 C 语言中工作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORD_LEN 15
int resizeArray(char (**wordList)[WORD_LEN], size_t *currentSize, size_t extent)
{
int result = 1;
char (*tmp)[WORD_LEN] = realloc(*wordList,
(*currentSize + extent) * sizeof **wordList);
if (tmp)
{
*currentSize += extent;
*wordList = tmp;
}
else
result = 0;
return result;
}
int main(void)
{
char *data[] = {"This", "is", "a", "test",
"of", "the", "Emergency",
"Broadcast", "System", NULL};
size_t i = 0, j;
char (*words)[WORD_LEN] = NULL;
size_t currentSize = 0;
for (i = 0; data[i] != NULL; i++)
{
if (currentSize <= i)
{
if (!resizeArray(&words, ¤tSize, 5))
{
fprintf(stderr, "Could not resize words\n");
break;
}
}
strcpy(words[i], data[i]);
}
printf("current array size: %lu\n", (unsigned long) currentSize);
printf("copied %lu words\n", (unsigned long) i);
for (j = 0; j < i; j++)
{
printf("wordlist[%lu] = \"%s\"\n", (unsigned long) j, words[j]);
}
free(words);
return 0;
}
回答by John Boker
Here is a little information on dynamically allocating 2d arrays:
以下是有关动态分配二维数组的一些信息:
回答by John Boker
char ** words = malloc( 1000 * sizeof(char *));
int i;
for( i = 0 ; i < 1000 ; i++)
*(words+i) = malloc(sizeof(char) * 15);
//....
for( i = 0 ; i < 1000 ; i++)
free(*(words+i));
free(words);
回答by Jens Gustedt
In modern C (C99) you have an additional choice, variable length arrays, VLA, such as that:
在现代 C (C99) 中,您有一个额外的选择,可变长度数组,VLA,例如:
char myWord[N];
In principle you could also do such a thing in two dimensions, but if your sizes get too big, you may risk a stack overflow. In your case the easiest thing would be to use a pointer to such an array and to use malloc/ reallocto resize them:
原则上你也可以在二维中做这样的事情,但如果你的尺寸太大,你可能会有堆栈溢出的风险。在您的情况下,最简单的方法是使用指向此类数组的指针并使用malloc/realloc调整它们的大小:
typedef char Word[wordlen];
size_t m = 100000;
Word* words = malloc(m * sizeof(Word));
/* initialize words[0]... words[m-1] here */
for (size_t i = 0; i < m; ++i) words[i][0] = 'void myWordFunc(size_t wordlen, size_t m, char words[m][wordlen]);
';
/* array is too small? */
m *= 2;
void *p = realloc(words, m*sizeof(Word));
if (p) words = p;
else {
/* error handling */
}
.
free(words);
This code should work (modulo typos) if wordlenis a constant or a variable, as long as you keep everything inside one function. If you want to place it in a function you should declare your function something like
wordlen只要您将所有内容都保留在一个函数中,此代码应该可以工作(模数拼写错误)如果是常量或变量。如果你想把它放在一个函数中,你应该像这样声明你的函数
that is the length parameters must come first to be known for the declaration of words.
也就是说,长度参数必须首先出现才能为words.

