4

好的,显然这有效:

void foo(size_t s) {
    int myArray[s];
    // ... use myArray...
}

这真的合法吗?我的意思是,它必须是,因为它可以编译(C 编译器会拒绝它为非常量)。我的问题的第一部分是:这是如何工作的?我假设它在堆栈上分配它?这与使用不同alloca()吗?

实际上,我发现了一些执行此操作的代码:

void bar(size_t chunkSize) {
    CFReadStreamRef foo = NULL;
    // ...some stuff to init foo...

    while (stuffToDo) {
        UInt8 buffer[chunkSize];
        // ...read some data from stream into buffer
        //    using CFReadStreamRead()...
    }
}

这行得通。但是,当我将缓冲区分配从循环内部移动到函数的第一行(就在foo声明之前)时,函数...停止工作。在调试器中,它首先访问局部变量,然后...退出。我没有看到任何异常被抛出,它没有崩溃,它只是程序继续运行(实际上函数返回一个字符串,返回值是NULL,这是返回变量被初始化的值)。我不确定发生了什么事。我的问题的第二部分是,鉴于第一部分,到底发生了什么?

4

1 回答 1

3

它在 C99 中是合法的,虽然很危险,而且是的 - 就像alloca.

因为它就像 alloca,所以在堆栈上分配时需要合理大小的数组。如果长度为零,我不确定这是否被定义,但如果数组“足够大”这样做,你肯定会导致堆栈溢出。

至于发生了什么——如果尺寸合理,将其拉出循环应该没有什么区别。我怀疑您看到未定义的行为是因为参数值太大(或者可能为 0)——您应该验证chunkSize参数。程序集会告诉您为什么将其从循环中拉出来会有所不同(假设程序中的其他所有内容都格式正确)。

于 2012-08-10T19:40:30.897 回答