【问题标题】:Why does sizeof(my_arr)[0] compile and equal sizeof(my_arr[0])?为什么 sizeof(my_arr)[0] 编译并等于 sizeof(my_arr[0])?
【发布时间】:2018-03-21 01:46:18
【问题描述】:

为什么这段代码会编译?

_Static uint32_t my_arr[2];
_Static_assert(sizeof(my_arr) == 8, "");
_Static_assert(sizeof(my_arr[0]) == 4, "");
_Static_assert(sizeof(my_arr)[0] == 4, "");

前 2 个断言显然是正确的,但我预计最后一行会失败,因为我的理解是 sizeof() 应该评估为整数文字,不能将其视为数组。换句话说,它会以与以下行失败相同的方式失败:

_Static_assert(4[0] == 4, "");

有趣的是,以下确实无法编译(应该做同样的事情,不是吗?):

_Static_assert(*sizeof(my_arr) == 4, "");

错误:一元'*'的无效类型参数(有'long unsigned int') _Static_assert(*sizeof(my_arr) == 4, "");

如果重要的话,我使用的是 gcc 5.3.0

【问题讨论】:

标签: c sizeof


【解决方案1】:

sizeof 不是函数。它是一个一元运算符,例如 !~

sizeof(my_arr)[0] 解析为sizeof (my_arr)[0],这只是sizeof my_arr[0] 带有多余的括号。

这就像!(my_arr)[0] 解析为!(my_arr[0])

通常,后缀运算符的优先级高于 C 中的前缀运算符。sizeof *a[i]++ 解析为 sizeof (*((a[i])++))(后缀运算符 []++ 首先应用于 a,然后是前缀运算符 @987654335 @ 和 sizeof)。

(这是sizeof 的表达式版本。还有一个类型版本,它采用带括号的类型名称:sizeof (TYPE)。在这种情况下,括号是必需的,并且是sizeof 语法的一部分。)

【讨论】:

  • 我当然知道 sizeof 是一元运算符而不是函数,但完全忘记了。哎呀。感谢您的详细解释。无论如何,[] 的优先级高于 * 的事实很有趣。
  • @melpomene 很有趣。我从没想过sizeof 是一元运算符。
  • 你不是说"... parses as sizeof (my_arr[0])"吗?只是添加一个空格并没有真正改变任何东西。
  • 我会推荐sizeof((my_array)[0])
【解决方案2】:

sizeof 有两个“版本”:sizeof(type name)sizeof expression。前者需要一对 () 围绕它的论点。但后者 - 以表达式作为参数的那个 - 在其参数周围没有()。无论您在参数中使用什么(),都被视为参数表达式的一部分,而不是sizeof 语法本身的一部分。

由于编译器知道my_arr 是对象名称,而不是类型名称,因此编译器实际上将您的sizeof(my_arr)[0] 视为sizeof 应用于表达式:sizeof (my_arr)[0],其中(my_arr)[0] 是参数表达式。数组名称周围的() 完全是多余的。整个表达式被解释为sizeof my_arr[0]。这相当于你之前的sizeof(my_arr[0])

(顺便说一句,这意味着您之前的@​​987654336@ 还包含一对多余的()。)

sizeof 的语法在某种程度上需要一对() 围绕其参数,这是一个相当普遍的误解。在解释sizeof(my_arr)[0]等表达时,这种误解会误导人们的直觉。

【讨论】:

  • 第一个版本的存在是为了让您可以在机器上检查整数的大小(从后面甚至没有 64 位机器!),但 int 不是一个有效的表达式,所以你不能使用第二种形式。
【解决方案3】:

[] 的优先级高于sizeof。所以sizeof(my_arr)[0]sizeof((my_arr)[0]) 是一样的。

Here 是指向优先表的链接。

【讨论】:

    【解决方案4】:

    您正在使用将表达式作为参数的sizeof 运算符版本。与采用类型的不同,它不需要 括号。因此,操作数只是(my_arr)[0],括号是多余的。

    【讨论】:

      猜你喜欢
      • 2017-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多