为什么 sizeof(my_arr)[0] 编译并等于 sizeof(my_arr[0])?
Why does sizeof(my_arr)[0] compile and equal sizeof(my_arr[0])?
为什么这段代码可以编译?
_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, "");
error: invalid type argument of unary '*' (have 'long unsigned int')
_Static_assert(*sizeof(my_arr) == 4, "");
如果重要的话,我使用的是 gcc 5.3.0
[]
的优先级高于 sizeof
。所以 sizeof(my_arr)[0]
与 sizeof((my_arr)[0])
相同。
Here 是 link 优先级 table。
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)
。在那种情况下,将需要括号和 sizeof
语法。)
您正在使用将表达式作为参数的 sizeof
运算符版本。与采用类型的类型不同,它不需要 括号。因此,操作数只是 (my_arr)[0]
,括号是多余的。
sizeof
有两个 "versions":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])
.
(这意味着,顺便说一句,您之前的 sizeof(my_arr[0])
还包含一对多余的 ()
。)
认为 sizeof
的语法在其参数周围需要一对 ()
是一种相当普遍的误解。在解释 sizeof(my_arr)[0]
.
等表达式时,这种误解会误导人们的直觉
为什么这段代码可以编译?
_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, "");
error: invalid type argument of unary '*' (have 'long unsigned int') _Static_assert(*sizeof(my_arr) == 4, "");
如果重要的话,我使用的是 gcc 5.3.0
[]
的优先级高于 sizeof
。所以 sizeof(my_arr)[0]
与 sizeof((my_arr)[0])
相同。
Here 是 link 优先级 table。
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)
。在那种情况下,将需要括号和 sizeof
语法。)
您正在使用将表达式作为参数的 sizeof
运算符版本。与采用类型的类型不同,它不需要 括号。因此,操作数只是 (my_arr)[0]
,括号是多余的。
sizeof
有两个 "versions":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])
.
(这意味着,顺便说一句,您之前的 sizeof(my_arr[0])
还包含一对多余的 ()
。)
认为 sizeof
的语法在其参数周围需要一对 ()
是一种相当普遍的误解。在解释 sizeof(my_arr)[0]
.