c++ - gcc 的动态大小数组在声明后是否与标准数组有效相同?
问题描述
在标准 C 和 C++中,数组的地址是数组本身,并sizeof
返回数组的大小,而不是指针。但是,gcc
动态大小数组的扩展是否提供相同的保证?
#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 文档,第 80 页:
sizeof 运算符产生其操作数的大小(以字节为单位),它可以是表达式或带括号的类型名称。大小由操作数的类型决定。结果是一个整数。如果操作数的类型是变长数组类型,则计算操作数;否则,不计算操作数,结果是一个整数常量。
所以你的第一个问题的答案是它由 C99 标准保证,gcc 大概遵循。
至于是否有时它的行为会与静态大小的数组不同......如果你使用它们的时候不会。
虽然我在 ISO C99 中找不到这方面的记录,但 gcc 似乎总是将 VLA 放在堆栈上 - 这是有道理的,因为它本质上是一个 alloca(),并且打算在块的末尾超出范围. 明智地使用,动态大小的数组的行为方式与静态大小的数组的行为方式之间永远不会有任何区别。然而,疯狂使用,是的,可能存在剥削(或其他骇人听闻的)行为的极端极端情况,其中进行剥削的人可能很高兴发现您正在使用另一种。
无论如何,你可能会觉得使用任何你觉得舒服的人都会觉得舒服。通常,(出于不同合理性的一两个原因)程序员更喜欢 malloc 而不是堆栈分配。
推荐阅读
- javascript - 当jquery已经加载时,如何从requirejs初始化jquery ui?
- amazon-cloudformation - AWS Cloudformation RDS EnablePerformanceInsights 不起作用
- ringcentral - RingCentral 从系统中自动取消授权
- php - IF 和 ELSE 都不会在 php 脚本流中触发!为什么?
- opengl - 如何使用 LWJGL3 渲染四边形?
- python - VBA脚本等待WScript.Shell返回时如何避免Excel冻结?
- c++ - 面临尝试解码 base64 图像的问题
- graphql - Gridsome source-filesystem 添加标签描述
- laravel - Laravel 队列链
- python - 在 settings.py 中导入时 Python 解耦会引发警告?[蟒蛇DJ]