【问题标题】:Sizeof operator Implementation : How it computes size at compile time?Sizeof 运算符实现:它如何在编译时计算大小?
【发布时间】:2013-05-30 09:35:04
【问题描述】:

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 如何实现和计算大小(对于浮点数、整数、...数据类型、变量、数组...)?

感谢任何代码!

【问题讨论】:

标签: c sizeof


【解决方案1】:

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

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

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

来自 C11,第 6.5.3.4 节 sizeof_Alignof 运算符,第 2 段:

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

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

【讨论】:

  • + 你今天是sizeof运营商的冠军:)
  • [如果sizeof不能应用于函数;有什么方法可以确保它](我正在使用代码块:mingw 如何严格地制作代码 c99)
  • 为什么要将sizeof应用于函数?
  • 是什么阻止您获得 C 规范并阅读它? “_Alignof 运算符产生其操作数类型的对齐要求。”
  • C11 规范草案:PDF link
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    Wikipedia 很好地解释了sizeof 的实现,详见here

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-09
      • 1970-01-01
      • 2018-05-16
      • 1970-01-01
      • 2016-06-05
      • 2016-12-26
      相关资源
      最近更新 更多