Are pointers to members of an anonymous union equal?
Asked Answered
B

1

6

C++11 allows an anonymous union to be defined in a function, and its members can be accessed as variables of the function. If I examine the pointers to the different members, they are the same, but the == operator says they're unequal.

Such strange behavior is typically the result of undefined behavior, but I don't see anything undefined in my code (I made sure to that both members are of the same type).

The behavior is different if I use a named variable of an unnamed union type. In this case, the pointers compare equal.

This program demonstrates both cases:

#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;
}

When compiled with -DNAMED it prints to identical pointers, and 1 (equal pointers). Without -DNAMED, it again prints identical pointers, but then 0 (unequal pointers).

Tested with g++ 5.4.0, Ubuntu 16.04, x86_64.

Balm answered 23/4, 2018 at 9:24 Comment(4)
Seems that this behavior changed since gcc 7. Might have been a compiler bug before.Reisinger
Clang also reports ADDR(a) == ADDR(b) on trunk.Bewray
This is not UB per [class.union]/1 and [basic.life]/6. In function-scope, the name of non-static data members of anonymous unions are injected into the function scope. You're taking the address of objects after their allocation storage has been allocated and before their lifetime begun. As long as you treat those pointers as if there were void*, your program is well-defined.Bewray
see https://mcmap.net/q/1915093/-is-it-well-defined-to-use-std-addressof-on-non-active-union-members-duplicate for instanceBewray
L
3

Your address checking is well defined (as YSC pointed out) and the standard guarantees that all members shall have the same address (cfr. [class.union]/3).

You must have stumbled upon a now fixed compiler bug.

Loveliesbleeding answered 23/4, 2018 at 9:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.