32

If I make a const union object (e.g in code below ), then no member assignment can be done in that. So is there any use of making a const union object, in any case ?

union un
{
    int i;
    float f;
    char c;
};
const union un a; 
/// ! a.i = 10; error.
timrau
  • 22,578
  • 4
  • 51
  • 64
cirronimbo
  • 909
  • 9
  • 19
  • 1
    In `c` it is not uncommon to interpret a union through a different member to that which was most recently set. And of course, it could be `const volatile` - i.e. we won't change it, but someone else might, and we need to be able to see that. – BoBTFish Aug 10 '12 at 08:12
  • 4
    Not if the whole damn union is `const`. – Puppy Aug 10 '12 at 08:14
  • @Xeo, it wouldn't compile without the "union" part when I tested with gcc. – Prof. Falken Aug 10 '12 at 08:14
  • @AmigableClarkKant: Yeah, I thought the question was only tagged C++ at first, but it's also C, so the `union` "elaborate type specifier" makes it portable. I rollback'd my rollback. :P – Xeo Aug 10 '12 at 08:15

2 Answers2

38

You can still initialize the union as follows:

const union un a = { .i = 100 }; 

then use it in your code.

user1202136
  • 11,171
  • 4
  • 41
  • 62
16

You can still assign it at declaration, for instance like this:

const union un a = {0};

Update: that notation sets the first of the union members.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
  • @R.MartinhoFernandes, all members, to zero. – Prof. Falken Aug 10 '12 at 08:15
  • Yeah, but that can only be done to assign the first member only ( or to set all to zero, as u mentioned) ! – cirronimbo Aug 10 '12 at 08:19
  • 2
    @R.MartinhoFernandes The first member. Formally, if you have `union un { short s; double d; }; union un a = {};`, the contents of `d` are undefined (and if `a` is const, there's no way you could legally access them anyway). – James Kanze Aug 10 '12 at 08:21
  • 2
    @AmigableClarkKant That's wrong (unless they've changed something in the last version of the C standard). In C90, union initialization is always the first member. In C99, there's an extended syntax (not present in C++) to initialize a different member, but there is still only one member which is initialized. – James Kanze Aug 10 '12 at 08:22
  • @R.MartinhoFernandes, sorry I was in a hurry. Yes, it's the first one. I was thinking about structs, where {0} is (nonstandard?) shorthand for setting all members. – Prof. Falken Aug 10 '12 at 08:27
  • C11 6.7.9/17 "Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union." – Lundin Aug 10 '12 at 08:55
  • C11 6.7.9/21 "If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate..." /--/ "...the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration." – Lundin Aug 10 '12 at 08:57
  • 1
    @JamesKanze So as far as I can tell from the standard, `un a = {0};` means: set the first union member to zero, and set the rest of the union members as if they were statics, ie set them to zero/NULL as well. – Lundin Aug 10 '12 at 08:59
  • @Lundin I don't think that's a reasonable interpretation. Consider what it would means for `un a { 42 };`. Initialization of the first element (a short in my example) to `42`, then the next to 0 would 1) overwrite the explicit initialization, and 2) mean that your first access would have to be the last element declared. – James Kanze Aug 10 '12 at 10:04
  • @Lundin (It's an interesting point, however. Perhaps a DR is in order.) – James Kanze Aug 10 '12 at 10:04
  • 1
    @JamesKanze I think in practice, it will work like "set everything to zero, then set the first member to 42". – Lundin Aug 10 '12 at 10:44
  • @Lundin That may be what implementations are doing, but there's no way I can read the statement you quoted to mean that. – James Kanze Aug 10 '12 at 13:52
  • @JamesKanze, why not? The standard usually specifies the end result, not the exact order. It's not concerned with *how* the union is stored in memory. I may be dense, but Lundins argument is sound to me. – Prof. Falken Aug 10 '12 at 13:58
  • 1
    @AmigableClarkKant His quote (which admittedly isn't exact, and I don't have the exact wording handy) says "set the first union member to [the value given], and set the rest of the union members as if they were static". If you write `un a { 42 };`, with my definition of `un`, this means setting `s` to 42, and then setting `d` to `0.0`. Since the text was written for `struct`, it doesn't mention order, but at the very least, setting them in the order would be legal. And if you set `d` to 0, then `s` will not be 42. – James Kanze Aug 10 '12 at 15:15
  • @JamesKanze, OK, then it gets kind of muddy. – Prof. Falken Aug 10 '12 at 15:46
  • @JamesKanze, still, I think standards are like laws. In the corner causes, you have to apply interpretetion. (No pun intended.) And then hope for the next revision to be more exact. – Prof. Falken Aug 10 '12 at 19:16
  • @AmigableClarkKant The problem is: given the exact wording you quote, there is no possible interpretation that is acceptable. Elsewhere, on the other hand, there is wording which says that the initializer of a union applies to the first member. Which suggests that that statement should have precedence. But IMHO, a DR is in order---and **if** all, or even most, actual implementations do set everything to 0, it would seem reasonable to standardize that behavior. – James Kanze Aug 13 '12 at 08:13