问题
I have a union in C like this:
union AUnion {
struct CharBuf {
char *buf;
size_t len;
} charbuf;
uint8_t num;
double fp_num;
};
My question is, can I guarantee that if given the following:
union AUnion u;
Then the following are true:
&u == &u.num
&u == &u.fp_num
&u == &u.charbuf
I.e they all start at the beginning of the memory segment where u
is stored.
In the case of this C program compiled with gcc version 5.3.0
and -std=c11
the above is true:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
union AUnion {
struct CharBuf {
char *buf;
size_t len;
} charbuf;
uint8_t num;
double fp_num;
};
int main(void)
{
union AUnion u;
printf("%d\n", ((void*)&u) == ((void*)&u.charbuf));
printf("%d\n", ((void*)&u.charbuf) == ((void*)&u.num));
printf("%d\n", ((void*)&u.num) == ((void*)&u.fp_num));
}
As it prints:
1
1
1
Compiling the code above as C++11 with the same compiler results in the same output as compiling it as C11.
But is this standardized behaviour? Is it undefined? Can I rely on this behaviour with most C compilers? Can I expect this behaviour with C++ compilers as well?
回答1:
In 6.7.2.1p16 the C standard guarantees that:
The size of a union is sufficient to contain the largest of its members. The value of at most one of the members can be stored in a union object at any time. A pointer to a union object, suitably converted, points to each of its members (or if a member is a bit- field, then to the unit in which it resides), and vice versa.
So, yes, you can rely on all members starting at the union
s address (note this is the same for the first member of a struct
).
The C++ standard includes a similar sentence with respect to C-style (i.e. only C-style members) union
s/struct
s, because C++ allows to pass union
s to C functions which does require this layout.The relevant section in the C++ standard is 9.5.
However, note there might be padding bits inside standard simple types (integers, floats). And their internal may vary (endianess). You also might violate strict aliasing rule (C: effective type).
回答2:
From my experience, I would say 'yes', though I've checked the C++14 standard and it even guarantees this. (c++11 will most likely have the same effects) Chapter 9.5 states: All non-static data members of a union object have the same address
So, you can depend on this behavior.
来源:https://stackoverflow.com/questions/36824637/memory-position-of-elements-in-c-c-union