【问题标题】:The result of "sizeof" depends on the location of the brackets. Why?“sizeof”的结果取决于括号的位置。为什么?
【发布时间】:2020-12-24 13:41:22
【问题描述】:

有一个代码:

 float x=-8.92;
 int y=5;
 printf("%u\n", sizeof x+y);
 printf("%u\n", sizeof (x+y));

结论:

9
4

为什么会发生这种情况(结果 9)?毕竟,这些都是简单的一元运算。

【问题讨论】:

  • sizeof x+y = sizeof(x)+y = 4+5 =9
  • sizeof x == 4 -> y == 5 -> 4 + 5 == 9
  • sizeof 不需要括号。括号仅对数据类型是必需的,例如sizeof (int).
  • 关于何时使用括号,请参阅这篇帖子here
  • @i486 sizeof 不需要括号。括号仅对数据类型是必需的,例如sizeof (int) 这意味着您应该始终使用它们。没关系,他们使这个程序所展示的错误成为不可能。

标签: c expression sizeof operator-precedence unary-operator


【解决方案1】:

sizeof 运算符的优先级高于二进制加法运算符 +。所以这个:

sizeof x+y

解析为:

(sizeof x)+y

因此,在第一个表达式中,您将获得 float 的大小,在您的系统上为 4,然后将值 5 添加到该值,得到 9。对于第二个表达式,子表达式 x+y 的类型为 @ 987654327@ 因为通常的算术转换,所以结果是 4,这就是打印的内容。

【讨论】:

  • 谢谢。我真的忘记了一元操作的优先级。
【解决方案2】:

这个表达式

sizeof x+y

等价于表达式

( sizeof x ) + y

所以sizeof x 等于sizeof( float )4 那么原始表达式的结果等于9

运算符sizeof 是一元运算符,其操作数又是一元表达式。那就是运算符特别定义为

sizeof unary-expression

x + y 是一个加法表达式,而变量x 作为主表达式又是一个一元表达式。因此,运算符被应用于变量 x。

另一方面,表达式( x + y ) 是主表达式,并且由于通常的算术转换具有float 类型。所以在这种情况下,当表达式写成sizeof( x + Y ) 时,运算符sizeof 再次应用于主(一元)表达式,等效于sizeof( float )

请注意,在printf 的调用中,您应该使用转换说明符%zu 而不是转换说明符%usizeof x + ysizeof( x + y ) 这两个表达式的类型都是size_t,这是一个实现定义的类型,通常是unsigned long 类型的别名。对于size_t 类型,定义了您将使用的转换说明符zu。否则,使用不正确的转换说明符调用 printf 可能会调用未定义的行为。

【讨论】:

  • 感谢您的详细解答。你能建议为什么你应该使用“%zu”而不是“%u”吗?
  • @Thepersonwiththequestion 查看我附加的答案。
【解决方案3】:

sizeof x+y(sizeof x) + y 相同,即sizeof 的优先级高于+

您的编译器应该警告您printf() 格式字符串 (%u) 和参数(size_tint 或其他)之间的不匹配 - 如果您使用的是 GCC,则应该添加 @ 987654329@ 到你的编译命令。

【讨论】:

  • 我一定会学习“-Wall-Wextra”。感谢您的提示。
  • 两次调用中参数的实际类型都是size_t,正确的格式说明符是%zu
  • @zwol, int + size_t 不一定是size_t。但是,是的,我确实得到了 xy 错误的方式 - 现在已修复。
  • @TobySpeight 我想技术上你可以size_t 小于intsize_t 的最小最大值为 65536,与 unsigned short 和 @ 相同987654340@) 但这对我来说似乎是一个非常奇怪的 ABI。你知道真正的 ABI 可以做到这一点吗?
  • 哦,是的,这听起来不太可能,我同意这一点。不,我不知道这样的系统(但我倾向于使用主流的 Unix 工作站,所以我不太可能)。此外,我很难记住算术的有符号和无符号值的常见类型。无论如何,感谢您指出我忘记了哪个变量是 float
【解决方案4】:

“sizeof”的结果取决于括号的位置。为什么?

因为“括号”覆盖了运算符的优先级。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-04-26
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多