【问题标题】:Cancellation of *& in ANSI CANSI C 中 *& 的取消
【发布时间】:2014-10-10 21:24:26
【问题描述】:

我们和一些朋友讨论了 ANSI C 中这个简单的以下代码的正确性。

#include <stdio.h>

int main(void)
{
    int a=2;
    printf("%d", *&a);
    return 0;
}

主要讨论是关于*&。如果 * 访问一个内存位置(又名指针)并 & 给出某个变量的内存地址...我认为 * 尝试访问一个 int 值作为内存地址(这显然不起作用),但我的朋友说 *& 它取消了自动(或解释为 &*)。我们使用 GCC 4.8.1 (MinGW) 对其进行了测试,并且代码 avobe 运行良好......我认为这是不对的。

你怎么看?认为这里有一个不好的解决方法(或者这只是愚蠢?)。感谢您的建议:)

【问题讨论】:

  • 当然...我知道可以减少它,但这就是我问这个的原因。在某些特定的内存情况下,可能会导致一些错误的编译器解释。
  • 您可能正在考虑按&amp;* 的顺序组合运算符的潜在问题,这已在 SO 上多次讨论过,包括此处的详细答案:stackoverflow.com/a/2896975/12711

标签: c pointers memory


【解决方案1】:

a 是一个左值:变量a
&amp;a 是指向此左值的指针。
*&amp;a&amp;a 指向的左值——即a

从技术上讲,*&amp;aa 并非在所有情况下都完全等效,因为在 a 所在的所有情况下都不允许使用 *&amp;a(例如,如果 a 被声明为 @987654332 @),但在你的例子中,它们是完全一样的。

【讨论】:

  • 有趣。很高兴知道 *& 在特定变量类型的情况下会导致错误的解释。 ;) 谢谢!
  • 没有不好的解释。只是&amp;a可能没有意义,可能不允许。口译没有问题。
  • 相反,*&amp;a 可能在a 无效的情况下有效:如果这是唯一一次获取a 的地址,则它没有被初始化,并且没有陷阱表示对于它的类型,这足以使它对任意值有效,而不是未定义的行为。
【解决方案2】:

C 标准中有一段有趣的摘录(作为脚注),即 C11 §6.5.3.2/4(脚注 102,强调我的),它直接讨论了这个方面:

因此,&amp;*E 等价于 E(即使 E 是空指针),并且 &amp;(E1[E2])((E1)+(E2))。如果E 是一个函数,这总是正确的 指示符或作为一元 &amp; 的有效操作数的左值 运算符,*&amp;E 是一个函数指示符或等于E 的左值。如果*P 是左值,T 是对象指针类型的名称,*(T)P 是 具有与T 指向的类型兼容的左值。

在您的情况下,a 是一个(可修改的)左值,它反映标准中的E 符号,并且它是标准要求的&amp; 运算符的有效操作数,因此*&amp;a(即*&amp;E)是一个等于 a 的左值。

请注意,您不能获取register 存储类变量的地址(如@Deduplicator 所指出的那样),因此它不符合这种减少的条件(即,即使是可修改的左值)。

【讨论】:

  • *&amp;a&amp;*a 是不同的东西。
  • @Deduplicator:是的,注意这两种情况都有解释。 *&amp;E 要求 E 是 a) 左值,b) &amp; 运算符的有效操作数。
【解决方案3】:

只要*&amp;a 有意义,那么*&amp;aa 就是同一个东西,可以互换。

【讨论】:

    【解决方案4】:

    一般情况下,*&amp;aa 相同。

    仍然存在极端情况:

    1. *&amp; 可能无效,因为&amp;a 不是左值或属于register-storage-class 是不允许的。

    2. 使用a 可能是未定义行为,因为a 是一个未初始化的无内存变量(registerauto-storage-class 可能已声明为register(地址从未采取))。

    将其应用于您的情况,省略 *&amp; 不会改变任何事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-21
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 2011-03-21
      相关资源
      最近更新 更多