繁体   English   中英

sizeof(array) 在运行时如何工作?

[英]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 标准:

6.5.3.4

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM