a.b 总是 (&a)->b 吗?
Is a.b always (&a)->b?
在 C 中,a.b
通常与 (&a)->b
同义。
这是否在所有情况下都是正确的,即使 a
是一些混乱的复合术语的宏?或者在任何版本的 C 中是否存在等效性不成立的任何边缘情况?
在 a.b
中,a
不需要是左值。
例如,如果 a
是一个扩展为函数调用的宏,那么 (&a)->b
就是约束违规。
这里有三个反例,都是基于应用&
:
的约束条件
a
是右值,因为它是函数返回的结构:
int bar(void)
{
extern struct S { int b; } foo(void);
return (&foo())->b;
}
Clang 说“错误:无法获取 'struct S' 类型右值的地址”。但它接受 return foo().b;
.
a
是右值,因为它是赋值的结果:
int bar(void)
{
struct S { int b; } x = {0};
struct S y;
return (&(y=x))->b;
}
Clang 说“错误:无法获取 'struct S' 类型右值的地址”。但它接受 return (y=x).b;
.
a
是用register
声明的,所以它的地址可能不会被占用:
int bar(void)
{
register struct S { int b; } a = {0};
return (&a)->b;
}
Clang 说“错误:请求的寄存器变量地址”。
In C, a.b
is normally synonymous with (&a)->b
.
C11
标准中没有任何内容要求 在所有情况下都具有这种等效性。相关部分(5.5.2.3 Structure and union members
)实际上对它们进行了明确的处理,该部分的脚注指出了误解的出处:
If &E
is a valid pointer expression (where &
is the "address-of" operator, which generates a pointer to its operand), the expression (&E)->MOS
is the same as E.MOS
.
换句话说,&E
必须有效才能使这个等价成立。它不的一个地方是:
#include <stdio.h>
struct xyzzy { int plugh; } twisty;
struct xyzzy getTwistyCopy(void) { return twisty; }
int main(void) {
twisty.plugh = 42;
printf("%d\n", ( getTwistyCopy() ).plugh);
printf("%d\n", ( &(getTwistyCopy()) )->plugh);
}
第一行 printf
行没问题,但第二行不行。那真的是因为你不能获取函数 return 值的地址。但是您仍然可以看到,对于任意 a
,a.b
和 (&a)->b
并不总是相同的。
在 C 中,a.b
通常与 (&a)->b
同义。
这是否在所有情况下都是正确的,即使 a
是一些混乱的复合术语的宏?或者在任何版本的 C 中是否存在等效性不成立的任何边缘情况?
在 a.b
中,a
不需要是左值。
例如,如果 a
是一个扩展为函数调用的宏,那么 (&a)->b
就是约束违规。
这里有三个反例,都是基于应用&
:
a
是右值,因为它是函数返回的结构:
Clang 说“错误:无法获取 'struct S' 类型右值的地址”。但它接受int bar(void) { extern struct S { int b; } foo(void); return (&foo())->b; }
return foo().b;
.a
是右值,因为它是赋值的结果:
Clang 说“错误:无法获取 'struct S' 类型右值的地址”。但它接受int bar(void) { struct S { int b; } x = {0}; struct S y; return (&(y=x))->b; }
return (y=x).b;
.a
是用register
声明的,所以它的地址可能不会被占用:
Clang 说“错误:请求的寄存器变量地址”。int bar(void) { register struct S { int b; } a = {0}; return (&a)->b; }
In C,
a.b
is normally synonymous with(&a)->b
.
C11
标准中没有任何内容要求 在所有情况下都具有这种等效性。相关部分(5.5.2.3 Structure and union members
)实际上对它们进行了明确的处理,该部分的脚注指出了误解的出处:
If
&E
is a valid pointer expression (where&
is the "address-of" operator, which generates a pointer to its operand), the expression(&E)->MOS
is the same asE.MOS
.
换句话说,&E
必须有效才能使这个等价成立。它不的一个地方是:
#include <stdio.h>
struct xyzzy { int plugh; } twisty;
struct xyzzy getTwistyCopy(void) { return twisty; }
int main(void) {
twisty.plugh = 42;
printf("%d\n", ( getTwistyCopy() ).plugh);
printf("%d\n", ( &(getTwistyCopy()) )->plugh);
}
第一行 printf
行没问题,但第二行不行。那真的是因为你不能获取函数 return 值的地址。但是您仍然可以看到,对于任意 a
,a.b
和 (&a)->b
并不总是相同的。