4

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、...datatypes、variables、array,...)?

任何代码表示赞赏!

4

3 回答 3

11

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

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

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

来自 C11,第 6.5.3.4 节sizeof_Alignof操作符,第 2 段:

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

编者按: sizeof返回 a size_t,而不是int,因此您应该使用%zu格式说明符而不是%d. 如果您打开适当的标志,您的编译器可能会警告您。

于 2013-06-04T05:14:26.380 回答
1

sizeofWikipedia很好地解释了实现,详见此处

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

于 2013-06-04T05:27:16.733 回答
0

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

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

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

于 2013-06-04T05:25:36.183 回答