C 如何声明未定义或没有初始大小的数组?

C 如何声明未定义或没有初始大小的数组?,c,C,我知道可以使用malloc,但我还不知道如何使用它 例如,我希望用户使用一个带有哨兵的无限循环输入几个数字,以在其中设置一个停止(即-1),但由于我还不知道他/她将输入多少,我必须声明一个没有初始大小的数组,但我也知道它不会像int-arr[]这样工作;在编译时,因为它必须有一定数量的元素 用像int-arr[1000]这样的夸张的大小声明它;这可能会起作用,但感觉很愚蠢(而且会浪费内存,因为它会将1000个整数字节分配到内存中),我想知道一种更优雅的方法来做到这一点。我可以想象的一种方法是使用

我知道可以使用
malloc
,但我还不知道如何使用它

例如,我希望用户使用一个带有哨兵的无限循环输入几个数字,以在其中设置一个停止(即-1),但由于我还不知道他/她将输入多少,我必须声明一个没有初始大小的数组,但我也知道它不会像int-arr[]这样工作;在编译时,因为它必须有一定数量的元素


用像int-arr[1000]这样的夸张的大小声明它;这可能会起作用,但感觉很愚蠢(而且会浪费内存,因为它会将1000个整数字节分配到内存中),我想知道一种更优雅的方法来做到这一点。

我可以想象的一种方法是使用链表来实现这种场景,如果您需要在用户输入指示循环终止的内容之前输入所有数字。(发布是第一个选项,因为我从未为用户输入这样做过,所以它看起来很有趣。浪费,但很有艺术性

另一种方法是进行缓冲输入。如果循环继续,分配缓冲区、填充缓冲区、重新分配缓冲区(不是优雅的,但对于给定的用例来说是最合理的)


我不认为这些描述是优雅的。可能,我会改变用例(最合理的)。

尝试实现动态数据结构,如一个通常的实现方式如下:

  • 分配一个初始(相当小)大小的数组
  • 读入这个数组,记录你读了多少元素
  • 一旦数组已满,重新分配它,将大小加倍并保留(即复制)内容
  • 重复,直到完成
我发现这种模式经常出现


这种方法的有趣之处在于,它允许人们在摊销的
O(N)
时间内将
N
元素逐个插入空数组,而不需要事先知道
N

现代C,又称C99,has,VLA。不幸的是,并不是所有的编译器都支持这一点,但如果您的编译器支持这一点,这将是另一种选择。

这可以通过使用指针和使用
malloc
在堆上分配内存来实现。 请注意,以后无法询问该内存块有多大。您必须自己跟踪阵列大小

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

int main(int argc, char** argv)
{
  /* declare a pointer do an integer */
  int *data; 
  /* we also have to keep track of how big our array is - I use 50 as an example*/
  const int datacount = 50;
  data = malloc(sizeof(int) * datacount); /* allocate memory for 50 int's */
  if (!data) { /* If data == 0 after the call to malloc, allocation failed for some reason */
    perror("Error allocating memory");
    abort();
  }
  /* at this point, we know that data points to a valid block of memory.
     Remember, however, that this memory is not initialized in any way -- it contains garbage.
     Let's start by clearing it. */
  memset(data, 0, sizeof(int)*datacount);
  /* now our array contains all zeroes. */
  data[0] = 1;
  data[2] = 15;
  data[49] = 66; /* the last element in our array, since we start counting from 0 */
  /* Loop through the array, printing out the values (mostly zeroes, but even so) */
  for(int i = 0; i < datacount; ++i) {
    printf("Element %d: %d\n", i, data[i]);
  }
}
#包括
#包括
#包括
int main(int argc,字符**argv)
{
/*将指针声明为整数*/
int*数据;
/*我们还必须跟踪我们的阵列有多大——我以50为例*/
常数int数据计数=50;
data=malloc(sizeof(int)*datacount);/*为50 int分配内存*/
在调用malloc之后,如果(!data){/*如果data==0,则由于某种原因分配失败*/
perror(“错误分配内存”);
中止();
}
/*此时,我们知道数据指向一个有效的内存块。
但是,请记住,这个内存并没有以任何方式初始化——它包含垃圾。
让我们从清理它开始*/
memset(数据,0,sizeof(int)*数据计数);
/*现在我们的数组包含所有零*/
数据[0]=1;
数据[2]=15;
data[49]=66;/*数组中的最后一个元素,因为我们从0开始计数*/
/*循环遍历数组,打印出值(大部分为零,但即使如此)*/
对于(int i=0;i
就这样。下面是一个更为复杂的解释,解释了为什么这样做:)

我不知道您对C指针了解多少,但C中的数组访问(如
array[2]
)实际上是通过指针访问内存的简写。要访问
数据
指向的内存,您需要编写
*数据
。这称为取消对指针的引用。由于
数据
的类型为
int*
,因此
*数据
的类型为
int
。现在来看一条重要信息:
(data+2)
的意思是“将2个整数的字节大小添加到
data
所指向的地址”


C中的数组只是相邻内存中的值序列<代码>数组[1]
就在
数组[0]
的旁边。因此,当我们分配一大块内存并想将其用作数组时,我们需要一种简单的方法来获取内存中每个元素的直接地址。幸运的是,C还允许我们在指针上使用数组表示法<代码>数据[0]与
*(数据+0)
的意思相同,即“访问
数据所指向的内存”
data[2]
表示
*(data+2)
,并访问内存块中的第三个
int

下面是一个示例程序,它将
stdin
读入一个根据需要增长的内存缓冲区。这很简单,应该可以让你对如何处理这类事情有一些了解。在一个实际的程序中,有一件事情可能会有所不同,那就是数组在每次分配中必须如何增长——我在这里把它保持得很小,以帮助简化调试过程。一个真正的程序可能会使用更大的分配增量(通常,分配大小会加倍,但如果要这样做,您可能应该将增量“限制”在某个合理的大小—当您进入数百兆字节时,将分配加倍可能没有意义)

此外,我在这里使用了对缓冲区的索引访问作为示例,但在实际程序中,我可能不会这样做

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


void fatal_error(void);

int main( int argc, char** argv)
{
    int buf_size = 0;
    int buf_used = 0;

    char* buf = NULL;
    char* tmp = NULL;    

    char c;
    int i = 0;

    while ((c = getchar()) != EOF) {
        if (buf_used == buf_size) {
             //need more space in the array

             buf_size += 20;
             tmp = realloc(buf, buf_size); // get a new larger array
             if (!tmp) fatal_error();

             buf = tmp;
        }

        buf[buf_used] = c; // pointer can be indexed like an array
        ++buf_used;
    }

    puts("\n\n*** Dump of stdin ***\n");

    for (i = 0; i < buf_used; ++i) {
        putchar(buf[i]);
    }

    free(buf);

    return 0;
}

void fatal_error(void)
{
    fputs("fatal error - out of memory\n", stderr);
    exit(1);
}
#包括
#包括
无效致命错误(无效);
int main(int argc,字符**argv)
{
int buf_size=0;
int buf_used=0;
char*buf=NULL;
char*tmp=NULL;
字符c;
int i=0;
而((c=getchar())!=EOF){
如果(使用的基本单位==基本单位大小){
//阵列中需要更多空间
buf_尺寸+=20;
tmp=realloc(buf,buf_size);//获取新的更大数组
如果(!tmp)致命错误();
日分