声明后,gcc 的动态大小数组是否与标准数组有效相同?
Are gcc's dynamically-sized arrays effectively identical to standard arrays after declaration?
在标准 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, %lun",
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而不是堆栈分配。
相关文章:
- 如何找到大小'x'数组是否完全填充,在C++?
- 任意大小的 constexpr 数组是否可以用作 switch 语句中的案例?
- 在 constexpr 构造函数中初始化数组是否合法?
- 以这种方式初始化的 char 数组是否会自动添加空终止符?
- 检查反向数组是否与原始数组相同
- 如何检查二维字符数组是否有空字
- 检查数组是否等于的最快方法?
- 确定数组是否可以旋转 3 个连续的数组元素进行排序?
- 如何检查数组是否包含多个元素?
- 我在代码中收到一个运行时错误,该错误如何通过修改最多一个元素来查找数组是否可以变得不减少
- c ++ 如何断言 char 数组与否,检查 char 数组是否以 "0" 开头或包含"0"
- 下课时的数组是否可以正常工作?
- C++全局常量数组:是否保证合并(优化)到一个副本中
- 在 C++17 中声明大小为 0 的数组是否合法
- 如果在执行过程中替换二进制文件,"const"数组是否驻留在内存中?
- 临时数组是否可能
- 使用二维数组作为一维数组是否正确?可能会导致未定义的行为左右?
- 当有多个查询时,检查某些子数组是否排序的有效方法是什么?
- 用于检查 char 数组是否仅包含允许的字符的函数
- 检查数组是否'right' (C++)