#include <stdio.h>
int func()
{
int a = 3, b = 4;
int c = a * b;
return c;
}
int main()
{
const int N = 10;
int arr[N];
printf("size = %ldn", sizeof(arr));
int x = 10;
const int SIZE = x;
int buf[SIZE];
printf("size = %ldn", sizeof(buf));
const int FN = func();
int buf2[FN];
printf("size = %ldn", sizeof(buf2));
return 0;
}
ubuntu 20 5.4.0-42-通用
gcc 9.3.0
编译:
gcc const_create_arr.c -Wall
不显示警告
输出:
size = 40
size = 40
size = 48
输出对应
最后一个FN是通过func((初始化的。我们知道func((return vlaue应该在运行时计算。但数组定义应该向编译器提供该数组的真实长度,以帮助编译器分配空间。所以我认为最后一个不应该在编译时通过。但这似乎是正确的。我想知道它是如何工作的。我的gcc是否对其进行了优化,并在编译时计算func返回。
在这三种情况下,您都在创建一个可变长度数组。对于要而不是为VLA的数组,其大小需要为整数常量表达式,并且具有const
限定符的变量(无论如何初始化(都不符合条件。
VLA的定义可以在C标准关于数组声明符的6.7.6.2p4节中找到:
如果大小不存在,则数组类型为不完整类型。如果大小为
*
而不是表达式,则数组类型为未指定大小的可变长度数组类型,只能在具有函数原型范围的声明或类型名称中使用;这样的阵列仍然是完整的类型如果大小是整数常量表达式,并且元素类型具有已知常量大小,则数组类型不是可变长度数组类型;否则,数组类型为可变长度数组类型
整数常数表达式的定义在第6.6p6:节中给出
整数常量表达式应具有整数类型,并且只能具有整数常量、枚举常量、字符常量、结果为整数常量的
sizeof
表达式、_Alignof
表达式和作为强制转换的立即数操作数的浮点常量的操作数。整数常量表达式中的强制转换运算符只能将算术类型转换为整数类型,但作为sizeof
或_Alignof
运算符操作数的一部分除外。
此定义中没有任何内容将const
限定变量限定为整数常量表达式,因此在运行时对三种情况中的每一种情况下的sizeof
运算符进行求值,因为数组都是VLA。
C具有可变长度的数组,因此如果事先定义了y
,则int x[y]
是有效的C。y
是否是const
并不重要,它只需要是> 0
就有意义了,而且足够小,不会用完整个堆栈。
在这种情况下,y
是12
,因此得到长度48(12 * sizeof(int)
,其中是4
(。这是在事后计算的,而不是像sizeof(int)
这样的琐碎事情那样提前计算。
在C++中,这不是标准定义的情况,但是一些编译器仍然会以C的方式进行。