不使用动态内存分配的 C 中的整数数组大小

Integer array size in C without using dynamic memory allocation

我需要声明一个大小为 symbolnum 的结构数组,但是因为 symbolnum 是变量,当我编写以下代码时 C 会产生错误:

extern int symbolnum;

struct SymbTab stab[symbolnum];

我已经试过了:

extern int symbolnum;
const int size = symbolnum;
struct SymTab stab[size];

有没有办法在不使用 malloc() 之类的动态内存分配函数或使用非常大的数字初始化数组大小的情况下实现这一点?

全局数组的大小必须在编译时固定。 VLA 只允许在函数内部使用。

如果 symbolnum 的值直到运行时才知道,您需要将 stab 声明为指针类型并为其动态分配内存。

或者,如果数组不超过几十KB,你可以在main函数中定义VLA,并设置一个全局指针指向它。

C11 及更高版本允许将可变长度数组作为可选功能。 C99 允许它们作为强制性功能。但是,在任何情况下都不允许在文件范围内使用 VLA,这似乎是您要实现的目标。

并且文件范围的 VLA 无论如何根据 C 语义是没有意义的。在文件范围内声明的对象具有静态存储持续时间,这意味着它们在程序执行开始时或之前存在,并且一直存在到程序终止。这意味着在变量可以取除初始值(零或整数常量表达式)以外的任何值之前需要数组长度,因此最好直接使用该初始值。

此外,即使 C99 是当前标准,一些 C 实现(尤其是 MSVC)也从未实现 VLA,并且由于该功能在当前标准中是可选的,因此无意这样做。

所以,

Is there a way to achieve this without using dynamic memory allocation functions like malloc() or initializing the size of array using a very big number?

这在一定程度上取决于您的确切需求(以及您的 C 实现),但很可能不是。一种可能性是在 main() 中使用本地 VLA,或者在其执行包含对数组的全部需求的其他函数中。如果您的 C 实现支持它们,您可以在那里声明一个 VLA,并传递指向它的指针。但是请注意,如果您需要的元素数量的上限确实是“非常大的数字”,那么这不太可能是合适的。 VLA 通常分配在堆栈上,这对它们的大小有一个相对严格的限制。

"Is there a way to achieve this without using dynamic memory allocation functions like malloc() or initializing the size of array using a very big number?"

如果你可以使用 variable length array (VLA),那么可以。下面说明了一种方法...

在全局 space 中使用 struct 定义,(例如,.c 文件的顶部,或在 .h 文件中)local 的数组实例struct 可以使用 VLA 创建,请记住 link 中提到的使用 VLA 的规定。然后可以将 VLA struct 数组作为函数参数传递,以在被调用函数中使用,或者更新并返回,就像使用任何其他函数参数一样。这是一个简单的例子:

//define either at top of .c file in file global space
//or in a header file that is included in any .c.  Then
//the typedef num_s can be used to create instances where needed
//
typedef struct SymbTab{
    int iVal;
    double dVal;
} SymbTab_s;

void populate_struct(size_t symbolnum, SymbTab_s *stab);

int main(void)
{
    size_t symbolnum = 0;//(using size_t). note, as you describe, this 
                         //comes after flex analysis normally, but for 
                         //this demo user input is used for simple 
                         // example of dynamically sizing array.
    printf("Enter symbolnum of struct array:\n");
    scanf("%zu", &symbolnum);
    SymbTab_s stab[symbolnum]; //dynamically sized array of SymbTab_s
    memset(stab, 0, sizeof(SymbTab_s) * symbolnum); //initialize new array
    populate_struct(symbolnum,  stab); //pass as function argument and update values
    //demo updated values
    for(int i=0; i < symbolnum; i++)
    {
        printf("%d, %lf\n", stab[i].iVal, stab[i].dVal);
    }
    return 0;
}

//simple function to demo form of parameters
//note size parameter is passed first
void populate_struct(size_t symbolnum, SymbTab_s *stab)
{
   for(int i=0; i < symbolnum; i++)
   {
       stab[i].iVal = i;
       stab[i].dVal = 1.0*i;
   }
}