【问题标题】:How is the sizeof operator ACTUALLY evaluatedsizeof 运算符是如何实际评估的
【发布时间】:2023-02-02 21:00:13
【问题描述】:

我的项目要求完全了解 sizeof 运算符的实际工作原理。在这方面的 C 标准规范是模糊的,依赖我对它的解释是危险的。我特别感兴趣什么时候和如何sizeof 应该被处理。

  1. 我以前的知识表明它是一个编译时运算符,我从未质疑过这一点,因为我从未过度滥用sizeof。然而:
    int size = 0;
    scanf("%i", &size);
    printf("%i\n", sizeof(int[size]));
    

    例如,这不能在编译时以任何方式进行评估。

    char c = '\0';
    char*p = &c;
    printf("%i\n", sizeof(*p));
    

    我不记得产生 U/B 的确切代码,但在这里,*p 是一个实际的表达式(RTL 一元取消引用)。据推测,这是否意味着 sizeof(c+c) 是一种通过表达式强制进行编译时评估的方法,还是会被编译器优化?

    1. sizeof 是否返回 int 类型的值,它是 size_t(在我的平台上是 ULL),还是实现定义的。

    2. This 文章指出“sizeof 的操作数不能是类型转换”,这是不正确的。类型转换与 sizeof 运算符具有相同的优先级,这意味着在同时使用两者的情况下,它们只是从右到左计算。 sizeof(int) * p 可能不起作用,因为如果操作数是大括号中的类型,则首先处理,但 sizeof((int)*p) 工作得很好。

    我要求对如何实施 sizeof 进行一些技术阐述。这对任何不想传播错误信息、不准确信息的人都有用,或者像我这样 - 从事直接依赖于它的项目。

【问题讨论】:

  • 您的第二个 sn-p 可以在编译时轻松评估。 *p 的类型固定为 char,其大小始终为 1。顺便说一句:sizeof 运算符的结果是 size_t 类型,它使用 %zu 格式说明符打印,而不是 @987654342 @.
  • @Gerhardh 是的(关于你的第一句话)我认为这不是正确的例子。
  • 关于您的第 (3) 点,这篇文章是正确的:在您的示例 sizeof((int)*p) 中,sizeof 的操作数不是类型转换;它是((int)*p),即类型转换括号内.这是一个差异,这与 sizeof 如何解释其参数非常相关。
  • sizeof 总是在编译时计算,可变长度数组除外,即使对于 c + c,结果也是 int:sizeof(c + c) == sizeof(int) 而 sizeof(3.14 * 2) == sizeof(double)
  • 对于它的价值,这个问题取决于 IMO,巨大VLA 与 C 中所有其他类型之间的区别。这当然是为什么它们最初不在语言中的原因;我相信这也解释了为什么它们是可选的,并且仍然没有在所有 C 程序员中普遍流行。

标签: c operators sizeof


【解决方案1】:

sizeof()per the (draft) C11 standard的语义:

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

注意“如果操作数的类型是可变长度数组类型,则计算操作数”。这意味着 VLA 的大小是在运行时计算的。

“否则,不计算操作数并且结果是一个整数常量”意味着结果在编译时计算。

The return type is size_t. Full stop:

两个运算符(sizeof() 和_Alignof())的结果值是实现定义的,并且它的类型(无符号整数类型)是size_t,在 <stddef.h> (和其他标头)中定义。

注意类型是size_t。不要使用unsigned long 或unsigned long long 或其他任何东西。始终使用size_t。

【讨论】:

    【解决方案2】:

    C 2018 6.5.3.4 2 指定了sizeof 的行为并说:

    ... 如果操作数的类型是可变长度数组类型,则计算操作数;否则,不评估操作数并且结果是整数常量。

    在您使用sizeof(int[size]) 的示例中,int[size] 的类型是可变长度数组类型,因此计算操作数1个,有效地计算程序执行期间的大小。

    在您使用 sizeof(*p) 的示例中,*p 的类型不是可变长度数组类型,因此不会计算操作数。 p 可能指向在程序执行期间创建的具有自动存储持续时间的对象这一事实是无关紧要的;这类型*p 的值在编译期间是已知的,因此不评估 *p,并且 sizeof 的结果是一个整数常量。

    脚注

    1个我们常常会想到一个类型名称(类型的规范,例如 int [size])与其说是可执行语句或表达式,不如说是被动声明,但 C 2018 6.8 4 告诉我们“还有一个隐式完整表达式,其中非常量大小的表达式对可变修改类型进行评估……”

    【讨论】:

      猜你喜欢
      • 2012-02-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-21
      • 2012-06-26
      • 1970-01-01
      • 2012-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多