[英]How sizeof(array) works at runtime?
我读过 C 中的 sizeof 运算符是在编译时解释的,因为在编译时编译器知道数组大小及其类型,sizeof 能够计算数组占用的字节数。但是 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;
}
这里的数组大小在编译时是未知的,那么它是如何正常工作的呢?
在 C89 中, sizeof
总是在编译时计算。 自 C99 和可变长度 arrays 起,当可变长度数组是sizeof
操作数中表达式的一部分时,它是在运行时计算的。
对sizeof
操作数的求值也是如此:它在 C89 中不被求值,但在 C99 中如果操作数是可变长度数组类型,它就会被求值。 例如:
int n = 5;
sizeof (int [n++]);
// n is now 6
由于您将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 单赋值形式出现的程序的产物。)
从 C99 标准:
sizeof
运算符产生其操作数的大小(以字节为单位),它可以是表达式或类型的括号名称。 大小由操作数的类型决定。 结果是 integer。如果操作数的类型是可变长度数组类型,则计算操作数; 否则,不计算操作数,结果为 integer 常量。
在这种情况下, sizeof()
在运行时进行计算。 编译器,因为它知道a
的大小基于数组声明时n
的值,所以生成代码以使用n
的适当值来为sizeof()
返回一个合理的值。
在 C99 中,并非所有sizeof()
的使用都可以在编译时完全评估并减少为运行时常量。
我读过 C 中的 sizeof 运算符在编译时被解释
除了 VLA 之外,所有情况下sizeof
都是在编译时确定的。 对于 VLA, sizeof
在运行时计算。
不管sizeof
是在编译时还是运行时计算的(或者更正式地说,它的结果是否是一个 integer 常量表达式), sizeof
的结果完全基于其参数的类型,而不是任何伴随可变长度的隐藏数据数组本身。 当然,当sizeof
应用于可变修改类型时,生成的程序必须在某处跟踪该大小。 但如果表达式足够简单并且它最初从中导出长度的变量不能改变,它可能会简单地重新计算它。 或者,它可以将类型的大小存储在某处(基本上在隐藏的局部变量中),但这不会以任何可观察的方式连接到 VLA object(例如,如果您将指针传递给 VLA 的第一个元素到另一个 function,该指针不能用于恢复 VLA 长度)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.