C语言中如何将长度由变量定义的数组存储在内存中?

3

我尝试过很多次搜索这个问题。静态数组通常存储在堆栈中,它们的大小在编译时确定。

例如:

int main()
{
    int n;
    scanf("%d", &n);
    int array[n];
    printf("%u", sizeof(array));
    return 0;
}

数组的大小因n的不同而变化。因此,数组应该在运行时以堆的形式存储,这样会更好吧?我对此感到困惑。请帮忙解答。谢谢!

@JoãoMendes; 为什么不呢? - haccks
1
@OldProgrammer;老兄!我觉得你需要更新一下了。 - haccks
1
@OldProgrammer 这已经正式成为可能已有16年以上的时间了。如果你计算gcc扩展的非官方时间,你会更接近于两个十年! - Sergey Kalinichenko
1
%u 不是正确的格式说明符。请使用 %zu - Spikatrix
1
C99支持这种行为,但我认为它不会通过任何公司的代码审查标准。我更喜欢使用alloca(3)(它的使用也不被赞同)来表示它是一个动态大小的堆栈变量。请参见:https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html - holgac
显示剩余2条评论
2个回答

6
这里的数组应该存储在堆中,因为大小是在运行时确定的吗? 答:它可以,但这不是唯一的方法。C编译器足够聪明,会将此可变长度数组的内存分配(通常称为“堆栈”)推迟到代码中数组大小已知的点。为了实现这一点,需要创建与sizeof相关的技巧。通常,sizeof在编译时评估;然而,可变长度数组改变了这一点,要求在VLAs上评估sizeof表达式在运行时。同样,编译器通过将VLA的实际大小存储在内存中的单独隐藏位置来提供其"启用技术"。

非常感谢!只有一个问题。这个功能在后续的gcc版本中是否可用? - Srikrishna Bhat
@SrikrishnaBhat gcc长期支持可变长度数组(VLA) - 我想它们开始于1999年VLAs成为标准之前。GNU编译器还将VLAs作为C ++的扩展支持,因为它们不是标准。 - Sergey Kalinichenko
每天学点新东西(或者在这种情况下,旧的)。我改正了。+1 - João Mendes

0

查看标准对这个特殊情况的说明:

C11: 6.5.3.4 (p2):

sizeof 运算符返回其操作数的大小(以字节为单位),其操作数可以是表达式或类型名称加括号。大小由操作数的类型确定。结果是一个整数。如果操作数的类型是可变长度数组类型,则会计算操作数;否则,不会计算操作数,结果是一个整数常量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接