为什么sizeof(my_arr)[0]编译并且sizeof(my_arr [0])?

bgo*_*erg 127 c sizeof

为什么这段代码会编译?

_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, "");
Run Code Online (Sandbox Code Playgroud)

前两个断言显然是正确的,但我本来期望最后一行失败,因为我的理解是sizeof()应该求值为整数文字,不能将其视为数组.换句话说,它将以与以下行失败相同的方式失败:

_Static_assert(4[0] == 4, "");
Run Code Online (Sandbox Code Playgroud)

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

_Static_assert(*sizeof(my_arr) == 4, "");
Run Code Online (Sandbox Code Playgroud)

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

如果重要,我正在使用gcc 5.3.0

mel*_*ene 192

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第一,则前缀运算符*sizeof).

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

  • 我当然知道sizeof是一个一元的操作符而不是一个函数,但完全忘了.Woops.谢谢你的详细解释.[]优先于*的事实无论如何都是有趣的. (14认同)
  • 你不是指``...解析为sizeof(my_arr [0])"`?只是添加一个空格并没有真正改变任何东西. (5认同)

AnT*_*AnT 45

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]).

(这意味着,BTW,你以前sizeof(my_arr[0])也包含一对多余的().)

这是一个相当普遍的误解,sizeof语法在某种程度上需要一对()围绕它的论点.这种误解是在解释这些表达时误导人们的直觉sizeof(my_arr)[0].


mch*_*mch 24

[]有更高的优势比sizeof.所以sizeof(my_arr)[0]是一样的sizeof((my_arr)[0]).

是一个优先表的链接.


Que*_*tin 7

您正在使用将sizeof表达式作为参数的运算符的版本.不同的是一个是需要一个类型,它并不需要括号.因此,操作数很简单(my_arr)[0],括号是多余的.