Sizeof运算符实现:它如何在编译时计算大小?

时间:2013-06-04 05:10:23

标签: c sizeof

Sizeof运算符是编译时运算符。在编译期间使用常量结果值转换sizeof表达式。 [异常可变参数模板c99]

通常,编译器会在编译时修复变量的大小。数组n的 。 但是,当我打印sizeof数组时,它给出了正确的大小? 这个代码是否在编译时为n?

分配内存

如何评估sizeof?

数组a []在函数中怎么样?

int fun(int n)
{
    char a[n+3];
    return sizeof(a);
}
int
main( )
{
    int i;
    while(i!=-1){
        scanf("%d",&i);
        int n[i];
        printf("\nsize: %d %d\n",fun(3),sizeof n);
    }
}

当我尝试这个: sizeof正确打印n的大小[(sizeof(int))* i]但函数总是给出错误的结果6?

如何实现sizeof并计算大小(对于float,int,...数据类型,变量,数组......)?

感谢任何代码!

3 个答案:

答案 0 :(得分:10)

正如您所提到的,sizeof计算通常由编译器在编译时进行。这并不总是正确的(例如,C99 / C11可变长度数组),但它是一个合理的近似值。

由于编译器知道(或决定)每种类型的大小,它只能在编译期间进行简单的常量替换。

对于您的示例,an都是可变长度数组,并且sizeof运算符在运行时应用。

从C11开始,第6.5.3.4节sizeof_Alignof运算符,第2段:

  

sizeof 运算符产生其操作数的大小(以字节为单位),该操作数可以是表达式或类型的带括号的名称。大小由操作数的类型确定。结果是整数。如果操作数的类型是可变长度数组类型,则计算操作数;否则,不评估操作数,结果是整数常量。

编辑说明:sizeof返回size_t,而不是int,因此您应使用%zu格式说明符而不是%d。如果打开相应的标志,编译器可能会发出警告。

答案 1 :(得分:1)

维基百科很好地解释了sizeof的实施,详见here

  

编译器有责任为每个目标平台正确实现sizeof运算符。在许多情况下,将为该平台提供官方应用程序二进制接口(ABI)文档,指定编译器必须符合的数据类型的格式,填充和对齐。在大多数情况下,sizeof是一个编译时运算符,这意味着在编译期间,sizeof表达式将被常量结果值替换。但是,应用于C99中引入的可变长度数组的sizeof需要在程序执行期间进行计算。

答案 2 :(得分:0)

sizeof的操作数不是可变长度数组(VLA)时,它sizeof并不真正“计算”任何东西。结果立即为编译器所知为编译时常量。在编译期间,该常量代替sizeof

如果操作数是VLA,则编译器只生成从VLA本身检索大小信息的代码。所以,是的,在一般情况下,典型的实现确实将VLA的大小存储在VLA本身内。在您的示例中,这意味着分配给a的内存也将包含存储n + 3值的位置。

当然,编译器可以在明显的情况下优化此评估,甚至在最明显的情况下用编译时常量替换它。在您的示例中,编译器可能足够聪明,不能从数组a中检索大小,而是立即意识到大小等于n + 3