gcc 的动态大小数组在声明后是否与标准数组有效地相同?

Are gcc's dynamically-sized arrays effectively identical to standard arrays after declaration?

在标准 C 和 C++ 中 the address of an array is the array itselfsizeof returns 数组的大小,而不是指针。但是,gcc 对动态大小数组的扩展是否提供相同的保证?

I tried this simple code:

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

int main(int argc, char ** argv)
{
    char foo[200];
    char bar[atoi(argv[1])];
    char *wibble = foo;

    printf("%p, %p, %lu, %p, %p, %lu, %p, %p, %lu\n",
           foo, &foo, sizeof(foo), bar, &bar, sizeof(bar), wibble, &wibble, sizeof(wibble));

    return 0;
}

输出如我所愿,等价:

0x7ffc7dd132e0, 0x7ffc7dd132e0, 200, 0x7ffc7dd131e0, 0x7ffc7dd131e0, 200, 0x7ffc7dd132e0, 0x7ffc7dd132c8, 8

但是,gcc 是否保证了这种等价性?是否有时使用动态大小而不是静态大小的数组会导致不同的程序行为?

※ 注意我感兴趣的是它是否有效,而不是如何使用 std::vector 更好地编写它,等等

直接来自 ISO C99 doc,第 80 页:

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.

所以第一个问题的答案是它由 C99 标准保证,gcc 大概遵循该标准。

至于是否有时它的行为会与静态大小的数组有所不同...如果您正确使用它们则不会。

虽然我在 ISO C99 中找不到这方面的记录,但 gcc 似乎总是在堆栈上放置一个 VLA - 这是有道理的,因为它本质上是一个 alloca(),并且打算在以下位置超出范围块的末尾。理智地使用,动态大小的数组的行为方式与静态大小的数组的行为方式之间永远不应该有任何区别。 疯狂使用 然而,是的,可能存在剥削(或其他骇人听闻的)行为的极端极端情况,在这种情况下,进行剥削的人可能会很高兴发现你正在使用一个而不是另一个。

无论如何,您可能会觉得使用任何一个您觉得舒服的都可以。通常,(出于不同合理性的一两个原因)程序员更喜欢 malloc 而不是堆栈分配。