简体   繁体   English

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

[英]Declare the size of array at runtime in standard C (not in C99)

Array needs size to be defined at compile time. 数组需要在编译时定义大小。 Is there any possibility to define the size of array at runtime using malloc or whatever? 是否有可能在运行时使用malloc或其他方法定义数组的大小?

This is entirely possible and very common. 这是完全可能的,而且非常普遍。 The right tool for the job is the malloc() function. 合适的工具是malloc()函数。 This allows you to dynamically create arrays of any size at runtime. 这使您可以在运行时动态创建任意大小的数组。 One example is to create an array at runtime with a size specified by the user. 一个示例是在运行时创建一个由用户指定大小的数组。

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;
}

This array (pointer to int ) can be used just like any other array, accessing its values with the [] operator. 可以像使用任何其他数组一样使用此数组(指向int指针),并使用[]运算符访问其值。

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

When you are done using this dynamically created array, use the free() function to give its memory back to the program. 使用此动态创建的数组完成操作后,请使用free()函数将其内存还给程序。

free(arr);

A second alternative to malloc() is the calloc() function. malloc()第二种替代方法是calloc()函数。 Because the block of memory returned by malloc() is not always initialized, it may contain garbage data. 由于malloc()返回的malloc()块并不总是初始化的,因此它可能包含垃圾数据。 If this is not desirable, the calloc() function can be used. 如果不希望这样,可以使用calloc()函数。 calloc() will initialize all of the elements of the returned memory to 0 for you. calloc()将为您初始化返回内存的所有元素为0 The call to calloc() is slightly different than the call to malloc() . 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;
}

In conclusion, the malloc() and free() functions are perfect for creating dynamic arrays in C . 总之, malloc()free()函数非常适合在C创建动态数组。 Remember to always call free() on memory that you reserved with malloc() (or calloc() ). 请记住,始终在使用malloc() (或calloc() )保留的内存上调用free() )。

To define the size of an array at compile time , you're able to use preprocessor macros for example to create a constant expression that can be updated at one position: 要在编译时定义数组的大小,您可以使用预处理器宏,例如,创建可以在一个位置更新的常量表达式:

#define ARR_LEN 50

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

If you want to determine the actual length at run time, then you'll have to use dynamic memory allocation: 如果要在运行时确定实际长度,则必须使用动态内存分配:

int arr_len = <user-input>;

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

// use the array

free(array_one);

VLA's are a c99 feature.. and not available in ANSI C / C89 / C90 whatever you want to call it. VLA是c99的一项功能。无论您想称它为什么,ANSI C / C89 / C90都不提供。

but VLA's introduce complexity that I don't like anyway, so in std C it is very common to do the following: (create a contiguous chunk of memory, which is just like a C array on the heap then access it by dereferencing the pointer, or directly with array syntax, both are equivalent and ok) 但是VLA引入了我不喜欢的复杂性,因此在std C中,通常执行以下操作:(创建连续的内存块,就像在堆上的C数组,然后通过解引用指针来访问它,或直接使用数组语法,两者都是等效的,可以)

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);
}

As other answers specified that, you can do that using malloc function to create a mxn matrix 1 of int s. 正如其他答案所指定的那样,您可以使用malloc函数创建一个intmxn矩阵1

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

Another way to do this is, though it is not dynamic nor efficient but make impression that it is dynamic: 做到这一点的另一种方法是,尽管它不是动态的也不是有效的,但给人的印象是它是动态的:

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

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

1 Note that although it seems that you are creating an array, but the arrays and pointers are two different types. 1请注意,虽然似乎您正在创建数组,但是数组和指针是两种不同的类型。 Arrays are not pointers and pointers are not arrays . 数组不是指针,指针也不是数组

An equivalent implementation to dynamic sized arrays can be achieved using alloca . 使用alloca可以实现动态大小数组的等效实现。 This function allocates space on system stack in the stack frame of the current function as if it was a local variable. 该函数在当前函数的堆栈帧中的系统堆栈上分配空间,就好像它是局部变量一样。 So, for example: 因此,例如:

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

would be implemeted as: 将实现为:

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

Allocated space is "freed" at function return. 函数返回时“释放”分配的空间。 alloca is not POSIX conforming, however. alloca不符合POSIX。

You can use calloc , malloc or realloc as per your requirements. 您可以根据需要使用calloc , malloc or realloc They are explained clearly here . 它们在这里清楚地解释

The malloc function allocates n bytes of memory, suitably aligned for storage of any type. malloc函数分配n个字节的内存,这些内存适当对齐以适合任何类型的存储。 This pointer is suitable for passing to free, which deallocates it, or realloc, which changes its size (and may move it to a different location). 该指针适合传递给free,以释放它,或重新分配,以改变其大小(并可能将其移动到其他位置)。 calloc allocates nmemb*size bytes, as if by malloc, and sets them to all bits zero. calloc就像通过malloc一样分配nmemb * size字节,并将其设置为所有零位。
It should be noted that all bits zero is not necessarily a valid null pointer or floating point 0 so calloc cannot be relied upon to correctly initialise all data types. 应该注意的是,所有位零不一定是有效的空指针或浮点0,因此不能依靠calloc正确初始化所有数据类型。

Here are some code samples 这是一些代码示例

#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);    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM