指向匿名联合成员的指针是不是相等?

Posted

技术标签:

【中文标题】指向匿名联合成员的指针是不是相等?【英文标题】:Are pointers to members of an anonymous union equal?指向匿名联合成员的指针是否相等? 【发布时间】:2018-04-23 09:24:32 【问题描述】:

C++11 允许在函数中定义匿名联合,并且可以将其成员作为函数的变量进行访问。如果我检查指向不同成员的指针,它们是相同的,但 == 运算符表示它们不相等。

这种奇怪的行为通常是未定义行为的结果,但我没有在我的代码中看到任何未定义的内容(我确保两个成员属于同一类型)。

如果我使用未命名联合类型的命名变量,行为会有所不同。在这种情况下,指针比较相等。

这个程序演示了这两种情况:

#include <iostream>
using namespace std;

#ifdef NAMED
// Create a named object of a union type
#define NAME n
#define ADDR(mem) &(NAME.mem)
#else
// Create an anonymous union in main()
#define NAME
#define ADDR(mem) &mem
#endif

int main()

    union 
        int a;
        int b;
     NAME;

    cout << "&a = " << ADDR(a) << endl;
    cout << "&b = " << ADDR(b) << endl;
    cout << "(&a==&b) = " << (ADDR(a) == ADDR(b)) << endl;

    return 0;

当使用-DNAMED 编译时,它会打印到相同的指针和 1(相同的指针)。如果没有-DNAMED,它会再次打印相同的指针,然后是 0(不相等的指针)。

使用 g++ 5.4.0、Ubuntu 16.04、x86_64 测试。

【问题讨论】:

似乎这种行为changed since gcc 7。之前可能是编译器错误。 Clang 还会在主干上报告 ADDR(a) == ADDR(b) 这不是每个 [class.union]/1 和 [basic.life]/6 的 UB。在函数作用域中,匿名联合的非静态数据成员的名称被注入到函数作用域中。在对象的分配存储被分配之后并且在它们的生命周期开始之前,您正在获取对象的地址。只要您将这些指针视为存在void*,那么您的程序就是定义良好的。 例如见***.com/a/49776289/5470596 【参考方案1】:

您的地址检查定义明确 (as YSC pointed out),并且标准保证所有成员都应具有相同的地址 (cfr.[class.union]/3)。

您一定偶然发现了一个现已修复的编译器错误。

【讨论】:

以上是关于指向匿名联合成员的指针是不是相等?的主要内容,如果未能解决你的问题,请参考以下文章

检查联合实例之间是不是相等的正确方法是啥?

第八次试验报告

实验报告

C++ - 包含数组的联合

联合中的大括号或相等初始化器

C++ 类查询错误:“”左侧必须指向类/结构/联合