我已经读过C中的sizeof运算符在编译时被解释,因为在编译时编译器知道数组大小及其类型,sizeof能够计算array所占用的字节数。但是sizeof是如何工作的以下代码:
#include<stdio.h>
#include<string.h>
int main()
{
int n;
scanf("%d",&n);
int a[n];
int s=sizeof(a);
printf("%d",s);
return 0;
}
这里的数组大小在编译时是不知道的,那么它是如何正常工作的?
答案 0 :(得分:27)
sizeof
始终在C89的编译时计算。从C99和可变长度数组开始,它是在运行时计算的,当可变长度数组是sizeof
操作数中表达式的一部分时。
对sizeof
操作数的评估相同:它不在C89中计算,但在C99中,如果操作数是可变长度数组类型,则计算它。例如:
int n = 5;
sizeof (int [n++]);
// n is now 6
答案 1 :(得分:14)
由于您将sizeof
应用于可变长度数组(其大小在编译时未完全知晓),因此编译器必须生成代码以在运行时执行其中的一部分。
gcc 4.6.3的高级优化器将您展示的代码转换为
scanf ("%d", &n);
t12 = (long unsigned int) n;
t13 = t12 * 4;
__builtin_alloca (t13);
t16 = (unsigned int) t12;
t17 = t16 * 4;
s18 = (int) t17;
printf ("%d", s18);
这能解释引擎盖下的情况吗? (不要被看似愚蠢的临时变量数量所拖延 - 这是我要求中间代码转储时程序的static single assignment形式的工件。)
答案 2 :(得分:7)
来自C99标准:
sizeof
运算符产生其操作数的大小(以字节为单位),可以是
表达式或类型的括号名称。大小由类型确定
操作数。结果是整数。 如果操作数的类型是可变长度数组
类型,操作数被评估;否则,不评估操作数,结果是
整数常数。
答案 3 :(得分:2)
在这种情况下,sizeof()
在运行时进行评估。编译器,因为它知道a
的大小基于数组声明时n
的值,生成代码以使用适当的n
值返回sizeof()
的合理价值。
在C99中,并非sizeof()
的所有用法都可以在编译时完全评估并减少到运行时常量。
答案 4 :(得分:2)
除了VLA之外,在所有情况下都在编译时确定我已经读过C中的sizeof运算符被解释为 编译时间
sizeof
。对于VLA,sizeof
在运行时进行评估。
答案 5 :(得分:1)
无论sizeof
是在编译时还是运行时计算(或者更正式地说,它的结果是否是整数常量表达式),sizeof
的结果纯粹基于其参数的类型,而不是随可变长度数组本身的任何隐藏数据。当然,当sizeof
应用于可变修改类型时,生成的程序必须在某处跟踪该大小。但是如果表达式足够简单并且它最初导出长度的变量不能改变,它可能只是重新计算它。或者,它可以在某处存储类型的大小(主要是在隐藏的局部变量中),但是这不会以任何可观察的方式连接到VLA对象(例如,如果您将指针传递给VLA的第一个元素)到另一个函数,该指针不能用于恢复VLA长度。)