为啥 sizeof(my_arr)[0] 编译并等于 sizeof(my_arr[0])?
Posted
技术标签:
【中文标题】为啥 sizeof(my_arr)[0] 编译并等于 sizeof(my_arr[0])?【英文标题】: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
【问题讨论】:
我怀疑( sizeof( my_arr ) )[ 0 ]
失败了。
最近的一个副本在这个语法上有另一个变化:Why does sizeof(x)++ compile?
【参考方案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])
Why is sizeof considered an operator?【参考方案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]
,括号是多余的。
【讨论】:
以上是关于为啥 sizeof(my_arr)[0] 编译并等于 sizeof(my_arr[0])?的主要内容,如果未能解决你的问题,请参考以下文章
C语言如何求一个二维数组有几行,还有为啥会提示gets()是一个未定义的标识符?
C语言 数组的问题,书上的例子,说a = sizeof(mu) / sizeof(mu[0])可以统计数组的元素个数,为啥?