【发布时间】:2011-02-05 06:34:51
【问题描述】:
第 6.5.3.2 节“地址和间接运算符”¶3 说(仅相关部分):
一元 & 运算符返回其操作数的地址。 ... 如果操作数是一元
*运算符的结果,则该运算符和&运算符都不会被计算,结果就好像两者都被省略了,除了对运算符的约束仍然适用并且结果不是左值。类似地,如果操作数是[]运算符的结果,则不会计算&运算符和[]隐含的一元*,结果就像删除了&运算符一样并且[]运算符更改为+运算符。 ...
这意味着:
#define NUM 10
int tmp[NUM];
int *i = tmp;
printf("%ti\n", (ptrdiff_t) (&*i - i) );
printf("%ti\n", (ptrdiff_t) (&i[NUM] - i) );
应该完全合法,打印 0 和 NUM (10)。标准似乎很明确,这两种情况都需要优化。
但是,它似乎不需要优化以下内容:
struct { int a; short b; } tmp, *s = tmp;
printf("%ti\n", (ptrdiff_t) (&s->b - s) );
这似乎非常不一致。我看不出上面的代码没有理由不打印sizeof(int) 加上(不太可能)填充(可能是4)。
简化&-> 表达式在概念上(恕我直言)与&[] 相同,即简单的地址加偏移量。它甚至是一个可以在编译时确定的偏移量,而不是可能在运行时使用 [] 运算符确定。
为什么这看起来如此不一致,有什么理由吗?
【问题讨论】:
-
我见过大量难的 C 和 C++ 标准问题,除了点赞、收藏和等待阅读答案,我不知道该怎么做。真的写了一个感觉很奇怪。
-
有趣 ... MSVC++ 打印 4!
-
@Abhi Rao - 带有 -Wall -Wextra -Werror 的 GCC (4.0) 编译并打印 4 没有任何抱怨。
-
现在我们已经消除了格式错误的空指针示例,我真的没有看到一个令人信服的用例来扩展此功能以涵盖
&->。显然,编译器可以(并且可能会)优化实际的取消引用并获取地址,但我只是没有看到一个令人信服的例子,其中&->的某些使用在当前语言规则下是未定义的但在给予&->与&*相同待遇的新规则下会得到很好的定义。 -
@James McNellis - 您可以使用非空指针创建
offsetofhack 词。据推测,如果标准要求对其进行优化,那么格式错误的背部更有可能起作用。
标签: c standards memory-address simplification