在C语言中,能否在运行时定义数组的大小?

8

刚学习C语言,非常感谢您的帮助。

在C语言中是否可以定义一个数组而不指定其大小或初始化它。

例如,我能否提示用户输入数字并将它们存储在int数组中? 我事先不知道他们会输入多少数字。

目前我所能想到的唯一方法是定义一个最大大小,但这不是理想的解决方案...

10个回答

15

你可以动态分配大小:

#include <stdio.h>

int main(int argc, char *argv[])
{
  int *array;
  int cnt;
  int i;

  /* In the real world, you should do a lot more error checking than this */
  printf("enter the amount\n");
  scanf("%d", &cnt);

  array = malloc(cnt * sizeof(int));

  /* do stuff with it */
  for(i=0; i < cnt; i++)
    array[i] = 10*i;

  for(i=0; i < cnt; i++)
    printf("array[%d] = %d\n", i, array[i]);

  free(array);

  return 0;
}

1
需要知道每次运行要添加多少个数字。否则使用realloc - Tordek
感谢您的帮助。我想我在第一篇帖子中没有清楚地表达问题。问题是我们不知道用户将输入多少个数字,用户也不知道。假设我们要求用户输入任意数量的数字,并为他计算平均值。他所需要做的就是输入数字,按回车键,再输入另一个数字......并在完成时输入Q。如何在不询问用户要输入多少个数字的情况下将这些数字保存在数组中?这将是C++中简单向量使用的方法... - rhr
抱歉,平均数不是一个好的例子,因为我们只需要总和,假设我们需要保存所有数字以进行一些花式计算... - rhr
@Bobby - 说到打字错误,“dynamically”中没有“o”。但这不是一个严重的问题。 - Chris Lutz
在C++中,“vector”类在其大小超出限制时会动态重新分配内存。而在C语言中,没有内置机制来实现这一点;你需要自己实现(使用realloc)或使用第三方库来实现向量或链表。 - dmazzoni

6
也许是这样的:

也许是这样:

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

/* An arbitrary starting size. 
   Should be close to what you expect to use, but not really that important */
#define INIT_ARRAY_SIZE 8

int array_size = INIT_ARRAY_SIZE;
int array_index = 0;
array = malloc(array_size * sizeof(int));

void array_push(int value) {
  array[array_index] = value;
  array_index++;
  if(array_index >= array_size) {
    array_size *= 2;
    array = realloc(array, array_size * sizeof(int));
  }
}

int main(int argc, char *argv[]) {
  int shouldBreak = 0;
  int val;
  while (!shouldBreak) {
    scanf("%d", &val);
    shouldBreak = (val == 0);
    array_push(val);
  }
}

这将提示输入数字并将它们存储在数组中,就像您要求的那样。当传递给0时,它将终止。
你可以创建一个访问器函数array_push来添加到数组中,在该函数中调用realloc以释放空间。每次分配的空间量增加一倍。最多会分配比所需内存多一倍的内存,最坏情况下,您将调用realloc log n次,其中n是最终预期的数组大小。
在调用malloc和realloc之后,您可能还想检查失败情况。我以上没有这样做。

1
在另一条评论中,您提到希望程序在用户输入“q”时停止要求数字。通过使用%s而不是%d调用scanf来实现这一点。然后,您将字符与“q”进行比较,并决定是否退出。接下来,您需要通过调用atoi将其转换为int类型。 - Joel
非常感谢,这很聪明,让我对解决问题有了不同的思路:不需要完全准确,先进行近似,然后再扩展。我可能会研究一下C++中向量的实现方式,我认为这将为解决这种问题提供一些见解。 - rhr

4

是的,完全正确。C99引入了VLA或变长数组。 一个简单的代码示例可能如下:

#include <stdio.h>

int main (void) {

    int arraysize;
    printf("How bid do you want your array to be?\n");
    scanf("%d",&arraysize);
    int ar[arraysize];  
    return 0;
}

2
代码块 := 使用四个空格进行缩进。快捷键是:选中代码块,然后按下CTL-k。希望对你有所帮助。 - wildplasser

3

按照定义,数组是固定大小的内存结构。您需要一个向量。由于标准C没有定义向量,您可以尝试查找库或手动实现。

您需要进行动态分配:您需要一个指向尚未知大小的内存地址的指针。请阅读有关 mallocrealloc 的内容。


另外,补充一下,一个流行的realloc()方法是,每当你需要realloc(因为你用完了空间),就将数组的大小加倍;这样你就尽可能少地进行realloc调用。 - BobbyShaftoe
每次重新分配时将大小加倍并不是为了本身最小化realloc调用的数量,而是为了保持良好的渐进效率。如果在每次重新分配时向向量添加一个常数增量,则推入n个元素需要O(n^2)的时间。如果在每次重新分配时将大小乘以某个因子>1,则每次推送都需要平摊的常数时间,并且整个过程需要O(n)的时间。 - Phil Miller

2
如果您只需要一个可以动态改变大小的数据结构,那么最好的选择是链表。您可以向列表添加数据,为其动态分配内存,这将更加容易!

+1,根据问题中的信息,一个简单的链表似乎是最好的选择。如果楼主在阅读它后能够澄清他将要用这些信息做什么,我们可能能够建议更合适的数据结构。 - Graphics Noob

1
如果你是一个初学者,也许你不想处理malloc和free。所以如果你使用GCC,你可以在堆栈上分配变量大小的数组,只需将大小指定为一个表达式即可。
例如:
#include <stdio.h>
void dyn_array(const unsigned int n) {
        int array[n];
        int i;

        for(i=0; i<n;i++) {
                array[i]=i*i;
        }
        for(i=0; i<n;i++) {
                printf("%d\n",array[i]);
        }
}
int main(int argc, char **argv) {
        dyn_array(argc);
        return 0;
}

但请记住,这是一个非标准扩展,因此如果可移植性很重要,您不应该依赖它。


1
这不是“非标准表达式”-在回答被写出来的时候,这已经是国际标准10年了。问题在于许多真正的非标准编译器,来自一些不称职的公司,如微软,它们甚至不支持10年前的标准。 - Antti Haapala -- Слава Україні

0
以上给出的答案是正确的,但有一个更正:函数malloc()会分配指定大小的内存块,并返回一个void*类型的指针,可以将其转换为任何形式的指针。 语法:ptr = (cast-type*) malloc(byte-size)

#include<stdio.h>
#include<cstdlib>
int main(int argc,char* argv[]){
int *arraySize,length;
scanf("%d",&length);
arraySize = (int*)malloc(length*sizeof(int));
for(int i=0;i<length;i++)
    arraySize[i] = i*2;
for(int i=0;i<length;i++)
    printf("arrayAt[%d]=%d\n",i,arraySize[i]);
free(arraySize);
}

0

你可以使用 malloc 动态地分配内存(也就是直到运行时才知道大小)。

C语言是一种底层语言:在使用完内存后必须手动释放;否则,你的程序将受到内存泄漏的影响。

更新

刚刚看到了你在另一个答案中的评论。

你正在寻求一个具有动态变化大小的数组。

然而,C语言没有语言/语法工具来实现这一点;你要么必须自己实现它,要么使用已经实现它的库。

参见这个问题:是否有自带glibc的C语言自动调整大小的数组/动态数组实现?


0

对于这种情况,您可能需要研究数据结构,例如:

  • 链表(非常适合此情况)
  • 各种树(二叉树、堆等)
  • 栈和队列

但是,对于实例化变量大小的数组,这并不是真正可能的。

最接近动态数组的方法是使用malloc及其相关命令(delete、realloc等)。

但在这种情况下,使用类似malloc的命令可能会导致需要扩展数组,这是一项昂贵的操作,需要初始化另一个数组,然后将旧数组复制到其中。列表和其他数据类型通常更擅长调整大小。


0
如果你正在寻找数组工具并且不想自己编写,建议尝试以下内容:
  1. Glib
  2. Apache APR
  3. NSPR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接