Getting sizeof an anonymous struct declared inside a union

D

David Resnick

I'm faced with a header with anonymous structures declared inside a
union like this:

union msg {
struct {
int a;
int b;
} s1;

struct {
char c;
double d;
double e;
} s2;
};

I want to apply the sizeof operator to one of these structs.
Changing the header is not currently an option, alas.

I currently can see two ways to do this as shown in this test program:

#include <stdio.h>
/* above union declaration here */
int main(void)
{
union msg foo;
printf("%lu\n", (unsigned long)sizeof(foo.s1));
printf("%lu\n", (unsigned long)sizeof(((union msg*)(NULL))->s2));

return 0;
}

Is the second legitimate? It compiles without complaint, but looks
dodgy.
I hate to create a fake instance of the union just to apply the sizeof
operator.
Or is there another way?

Thanks,
-David
 
V

vipvipvipvip.ru

Is the second legitimate? It compiles without complaint, but looks
dodgy.
Yes it is.
Consider the following:
int *p;
printf("sizeof(*p) == sizeof(int) == %zu\n", sizeof *p);
This would've been invalid code if what p pointed to was really
accessed.
 
B

Ben Bacarisse

David Resnick said:
I'm faced with a header with anonymous structures declared inside a
union like this:

union msg {
struct {
int a;
int b;
} s1;

struct {
char c;
double d;
double e;
} s2;
};

I want to apply the sizeof operator to one of these structs.
Changing the header is not currently an option, alas.

I currently can see two ways to do this as shown in this test program:

#include <stdio.h>
/* above union declaration here */
int main(void)
{
union msg foo;
printf("%lu\n", (unsigned long)sizeof(foo.s1));
printf("%lu\n", (unsigned long)sizeof(((union msg*)(NULL))->s2));

return 0;
}

Is the second legitimate?

I think so, yes. Unless the union contains a variable length array,
the operand of sizeof is not evaluated.
It compiles without complaint, but looks
dodgy.
I hate to create a fake instance of the union just to apply the sizeof
operator.
Or is there another way?

You can use a compound literal (new in C99) which won't actually
'make' anything either:

sizeof (union msg){{0,0}}.s2;

but this requires you to know how to initialise a 'union msg' (so the
code changes if the structure changes) and you need C99. Since you
carefully cast sizeof's result to unsigned long (rather then using
%zu) I suspect you are not using C99.
 
?

=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F

You can use a compound literal (new in C99) which won't actually 'make'
anything either:

sizeof (union msg){{0,0}}.s2;

but this requires you to know how to initialise a 'union msg' (so the
code changes if the structure changes)

All object and incomplete types can be initialised to {0}, whether
they're arrays, structures, unions, or scalars.

sizeof (int) {0} ==
sizeof (int)
sizeof (int [2]) {0} ==
sizeof (int [2])
sizeof (union { struct { union { int m; } u; } s; }) {0} ==
sizeof (union { struct { union { int m; } u; } s; })
 
K

Keith Thompson

Yes it is.
Consider the following:
int *p;
printf("sizeof(*p) == sizeof(int) == %zu\n", sizeof *p);
This would've been invalid code if what p pointed to was really
accessed.

Yes, it would have. Fortunately, the argument to sizeof is never
evaluated unless it's a VLA.
 
B

Ben Bacarisse

Harald van Dijk said:
You can use a compound literal (new in C99) which won't actually 'make'
anything either:

sizeof (union msg){{0,0}}.s2;

but this requires you to know how to initialise a 'union msg' (so the
code changes if the structure changes)

All object and incomplete types can be initialised to {0}, whether
they're arrays, structures, unions, or scalars.

sizeof (int) {0} ==
sizeof (int)
sizeof (int [2]) {0} ==
sizeof (int [2])
sizeof (union { struct { union { int m; } u; } s; }) {0} ==
sizeof (union { struct { union { int m; } u; } s; })

Duh! I tried that, and concluded that the rules must be different for
compound literals, but it was just the compiler giving me a helpful
warning.
 
D

David Thompson

All object and incomplete types can be initialised to {0}, whether
they're arrays, structures, unions, or scalars.
Object types yes, and array of unknown size (but not VLA); but not the
other incomplete types: tag-only struct/union, and void.

- formerly david.thompson1 || achar(64) || worldnet.att.net
 
?

=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F

Object types yes, and array of unknown size (but not VLA); but not the
other incomplete types: tag-only struct/union, and void.

You can't define objects of undefined struct/union types or of void type
anyway, so whether the initialiser would work if you could doesn't really
matter, but VLAs are a definite exception. Thanks, I'll try to remember
that.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top