views:

278

answers:

3

I wonder why the following does not work with Visual studio

typedef struct {
    float x, y;
} complexf;

typedef union {
    complexf f;
    long long d;
} rope;

int main(void)
{
    complexf a;
    rope z = {a};
}

The error is at line rope z = {a}, cannot convert from complexf to float. If the first member of the union is not a typedef, then it works. Is this a compiler bug, or a dark edge of C ?

A: 

in VS 6.0 when I compile with /W4 I get

warning C4204: nonstandard extension used : non-constant aggregate initializer

so that makes me think it's not standard C and you are in compiler dependent land.

jcopenha
A: 

Works fine on my G++ 3.4.4 on Cygwin.

Except for the ':' at the end needing a change to ';'.
And, I changed '__int64' to 'long long'.


With my stronger bias towards C for such code, I would have written,

 rope z = *(rope *)&a;

to force it on to the C++ compiler :-).
But, don't do that...

The right way to go is of course, as David notes in his comment,

rope z; z.f = a;
nik
the type punning through pointer is very ugly - I have never seen any case where it was useful. Union is much better for type punning.
David Cournapeau
Infact, it is likely to fool the compiler into overlooking your errors. Yet, I have seen it being used.
nik
I've done type punning through pointer casts myself out of laziness, but using unions is preferable: GCC optimizes them better and they avoid possible alignment issues
Christoph
+2  A: 

ANSI C standard (aka C89), 3.5.7:

All the expressions in an initializer for an object that has static storage duration or in an initializer list for an object that has aggregate or union type shall be constant expressions.

The latter part of this restriction has been dropped in C99, which isn't properly supported by VS.

Christoph
Thanks. I am a bit surprised that this is ok, though: rope z; z.f = a;
David Cournapeau
What exactly are you surprised about? That you can assign whole structeres? That's perfectly valid (for unions as well, but not for arrays).
Christoph