为什么sizeof(my_arr)编译并等于sizeof(my_arr )?
为什么这个代码编译?
_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, "");
前两个断言显然是正确的,但我会期望最后一行失败,因为我的理解是sizeof()
应该计算为一个整数文字,不能被视为一个数组。 换句话说,就像下面一行失败一样:
_Static_assert(4[0] == 4, "");
有趣的是,下面的确不能编译(应该做同样的事情,不是吗?):
_Static_assert(*sizeof(my_arr) == 4, "");
错误:一元'*'的无效types参数(有'无符号长整型')_Static_assert(* sizeof(my_arr)== 4,“”);
如果重要的话,我使用的是gcc 5.3.0
sizeof
不是一个函数。 这是一个一元运算符!
或~
。
sizeof(my_arr)[0]
parsing为sizeof (my_arr)[0]
,只是sizeof my_arr[0]
与冗余括号。
这就像!(my_arr)[0]
parsing为!(my_arr[0])
。
通常,后缀运算符的优先级高于前缀运算符的sizeof *a[i]++
parsing为sizeof (*((a[i])++))
(后缀运算符[]
和++
适用于第一个,然后是前缀运算符*
和sizeof
)。
(这是sizeof
的expression式版本,还有一个types版本,它带有一个加括号的types名称: sizeof (TYPE)
。在这种情况下,parens将是必需的,并且是sizeof
语法的一部分。
sizeof
有两个“版本”: sizeof(type name)
和sizeof expression
。 前者需要一对()
围绕其参数。 但后者 – 以expression为论点的 – 并没有围绕它的论点。 无论在参数中使用什么,都被视为参数expression式的一部分,而不是sizeof
语法本身的一部分。
由于编译器将my_arr
称为对象名称,而不是types名称,因此编译器将sizeof(my_arr)[0]
实际上视为应用于expression式的sizeof (my_arr)[0]
: sizeof (my_arr)[0]
,其中(my_arr)[0]
是参数expression式。 ()
周围的数组名称是纯粹多余的。 整个expression式被解释为sizeof my_arr[0]
。 这相当于您之前的sizeof(my_arr[0])
。
(这意味着,顺便说一下,你以前的sizeof(my_arr[0])
也包含一对多余的()
。)
这是一个相当普遍的误解, sizeof
的语法在某种程度上需要一对()
的参数。 这种误解是在解释sizeof(my_arr)[0]
等expression式时误导人们的直觉。
[]
比sizeof
有更高的优先权。 所以sizeof(my_arr)[0]
和sizeof((my_arr)[0])
。
这是一个优先表的链接。
您正在使用以expression式作为参数的sizeof
运算符的版本。 与采用types的不同,它不需要括号。 因此,操作数只是(my_arr)[0]
,括号是多余的。