在标准 C 中(不在 C99 中)在运行时声明数组的大小

Posted

技术标签:

【中文标题】在标准 C 中(不在 C99 中)在运行时声明数组的大小【英文标题】:Declare the size of array at runtime in standard C (not in C99) 【发布时间】:2014-07-06 09:13:19 【问题描述】:

数组需要在编译时定义大小。是否有可能在运行时使用malloc 或其他方式定义数组的大小?

【问题讨论】:

编译时还是运行时?您的标题与您的问题正文不匹配? 说出你已经尝试过的,并表明一些努力是可能的。 现有答案如何无法回答您的问题? @Mario:其实我觉得这个问题已经很清楚了。该语言将数组大小限制为可以在编译时确定的值(这就是问题正文中的第一句所指的内容)。 OP 希望能够在运行时指定数组大小。 您能举一些例子说明您希望如何使用这样的功能吗? 【参考方案1】:

要在编译时定义数组的大小,您可以使用预处理器宏来创建一个可以在一个位置更新的常量表达式:

#define ARR_LEN 50

char array_one[ARR_LEN];
char array_two[ARR_LEN];

如果您想在运行时确定实际长度,则必须使用动态内存分配:

int arr_len = <user-input>;

char *array_one = (char*)malloc(sizeof(char) * arr_len);

// use the array

free(array_one);

【讨论】:

您不一定能根据分配/使用变量的位置将其设为单行。还是我错过了什么? 该声明最好写成char *array_one = malloc(arr*len * sizeof *array_one);。不必强制转换malloc 的结果; void* 结果将隐式转换为所需的指针类型,并且强制转换在某些情况下可以掩盖错误。如果稍后更改元素类型,使用sizeof *ptr_var 而不是sizeof (element_type) 会使代码更加健壮。你应该经常检查malloc是否失败(它通过返回一个空指针来报告)。【参考方案2】:

使用alloca 可以实现与动态大小的数组等效的实现。该函数在当前函数的栈帧中分配系统栈空间,就好像它是一个局部变量一样。所以,例如:

void fun(int i) 
   int a[i];
   ...

将被实现为:

void fun(int i) 
   int *a = alloca(i * sizeof(int));
   ...

分配的空间在函数返回时“释放”。但是,alloca 不符合 POSIX。

【讨论】:

alloca 不符合 POSIX 或 ISO C。【参考方案3】:

这是完全可能的并且非常普遍。适合这项工作的工具是malloc() 函数。这允许您在运行时动态创建任意大小的数组。一个例子是在运行时创建一个用户指定大小的数组。

int main(int argc, const char **argv) 

    printf("How long should the dynamic array be?");

    int length;
    scanf("%d", &length);

    // dynamically create the array with malloc

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

    return 0;

这个数组(指向int 的指针)可以像任何其他数组一样使用,使用[] 运算符访问它的值。

int fifthValue = array[4]; // assumes array was malloc()'d with at least 5 mem slots.

使用完这个动态创建的数组后,使用free() 函数将其内存还给程序。

free(arr);

malloc() 的第二个替代方法是 calloc() 函数。因为malloc()返回的内存块并不总是初始化,它可能包含垃圾数据。如果不希望这样做,可以使用calloc() 函数。 calloc() 将为您将返回内存的所有元素初始化为0。对calloc() 的调用与对malloc() 的调用略有不同。

int main(int argc, const char **argv) 

    printf("How long should the dynamic array be?");

    int length;
    scanf("%d", &length);

    // dynamically create the array with calloc and initialize it to 0

    int *array = calloc(length, sizeof(*array));

    return 0;

总之,malloc()free() 函数非常适合在C 中创建动态数组。请记住始终在您使用malloc()(或calloc())保留的内存上调用free()

【讨论】:

【参考方案4】:

VLA 是 c99 功能.. 在 ANSI C/C89/C90 中不可用,无论您想如何称呼它。

但是 VLA 引入了我无论如何都不喜欢的复杂性,因此在 std C 中执行以下操作是很常见的:(创建一个连续的内存块,就像堆上的 C 数组然后通过解引用指针,或者直接用数组语法,都是等价的,ok)

typedef struct

    int a;
    int b;
MyStruct;

int main(int argc, const char * argv[])

    size_t numberOfElements = 5;
     //this will create a buffer numberOfElements * sizeof(MyStruct) in size and init each byte to 0;
    MyStruct * myAlmostArray = calloc(sizeof(MyStruct),numberOfElements);

    //do Stuff
    int i;
    for(i=0;i<numberOfElements;i++)
    
        //gets the array (not needed in this example)
        MyStruct s = myAlmostArray[i];
        s.a = 3;
        s.b = i;
        //write the stack array back to the heap allocated psuedo array
        myAlmostArray[i] = s;

        //or slightly different example where you mutate the heap memory directly
        myAlmostArray[i].a = 3;
        myAlmostArray[i].b = i;

        //or the same thing written differently
        MyStruct * m = myAlmostArray + i;
        m->a = 3;
        m->b = i;
    
    // free the memory
    free(myAlmostArray);

【讨论】:

【参考方案5】:

您可以根据自己的要求使用calloc , malloc or realloc。都解释清楚了here。

malloc 函数分配 n 字节的内存,适合任何类型的存储。该指针适用于传递给释放它的 free 或 realloc,它改变它的大小(并可能将它移动到不同的位置)。 calloc 分配 nmemb*size 字节,就像通过 malloc 一样,并将它们设置为所有位为零。 应该注意的是,所有位 0 不一定是有效的空指针或浮点 0,因此不能依赖 calloc 来正确初始化所有数据类型。

这里是一些代码示例

#include<stdlib.h>
/* 
    some code
*/
n = some_calculation() ; // array size generated at runtime
// data_type is the type of the array eg. int or struct
//using calloc ,it will set allocated values to zero or NULL as per their data_type
data_type *array = calloc(n,sizeof(data_type)) ;
// using malloc , it will only allocate adresses, they may contain garbage values
data_type *array = (data_type *)malloc(n);
// using realloc
array = (data_type *) realloc(array, new_n);
// after you have used your array , you can free the memory allocated
free(array);    

【讨论】:

【参考方案6】:

正如其他答案所指定的那样,您可以使用malloc 函数来创建mxn 矩阵1ints。

int **matrix = malloc(m * sizeof(int *));
for(int i = 0; i < n; i++)
    matrix[i] = malloc(n * sizeof(int));  

另一种方法是,虽然它不是动态的,也不是有效的,但给人的印象是它是动态的:

#define m 100
#define n 100
//...

int main()

    int arr[m][n], row, col;
    scanf("%d %d", row, col);
    arr[row][col];
    //...
  

1 注意,虽然看起来你是在创建一个数组,但是数组和指针是两种不同的类型。 Arrays are not pointers and pointers are not arrays.

【讨论】:

以上是关于在标准 C 中(不在 C99 中)在运行时声明数组的大小的主要内容,如果未能解决你的问题,请参考以下文章

DEV-C++是否不完全支持C99标准?

C99 在运行时如何计算可变长度数组的大小?

堆栈中的动态数组?

C99 是不是保证数组是连续的?

vscode支持c99标准

GCC和C99标准中inline使用上的不同之处。inline属性在使用的时候,要注意以下两点:inline关键字在G