sizeof a union

M

Mockey Chen

My friend ask me a question as following:

give a union SU define as:
typedef union _SU
{
short x;
struct y{
char a;
short b;
char c;
};
}SU;

what is the sizeof (SU)?

My compiler tell me the answer is 6.
I want to know why the answer is 6.

Thanks in advance.

--
Regards.
Mockey Chen
Email: (e-mail address removed)
 
S

Sven Hesse

Mockey Chen said:
typedef union _SU
{
short x;
struct y{
char a;
short b;
char c;
};
}SU;

what is the sizeof (SU)?

My compiler tell me the answer is 6.
I want to know why the answer is 6.

Short answer: Why not?

Somewhat longer answer:
Maybe shorts are 4 bytes wide on your machine... Or maybe
there's alignment... Or... ... ...
 
R

robotnik

Sven said:
Short answer: Why not?

Somewhat longer answer:
Maybe shorts are 4 bytes wide on your machine... Or maybe
there's alignment... Or... ... ...

The size of the structure struct y is 6 bytes.The size of short is 2
bytes.There are 3 variables in the structure.each character also has a
size of two bytes.
hence 3*2 bytes= 6 bytes
 
S

Sven Hesse

robotnik said:
each character also has a size of two bytes.

....Err, since when is a char 2 bytes wide? If I'm not totally mistaken,
a char has _always_ a size of 1 byte...
 
J

John Bode

Mockey said:
My friend ask me a question as following:

give a union SU define as:
typedef union _SU
{
short x;
struct y{
char a;
short b;
char c;
};
}SU;

what is the sizeof (SU)?

My compiler tell me the answer is 6.
I want to know why the answer is 6.

The size of a union is the size of its largest member; in this case,
that would be struct y.

The most likely reason that the struct is 6 bytes long instead of 5 is
due to alignment restrictions; many architectures require multibyte
objects to start on mod 2 or mod 4 addresses, so there's probably an
unused byte between the struct members a and b. For fun, try
rearranging the contents of struct y and see if you get a different
result.
 
T

Tatu Portin

Sven said:
...Err, since when is a char 2 bytes wide? If I'm not totally
mistaken, a char has _always_ a size of 1 byte...


Size of char is _at least_ 1 byte.
 
S

Sven Hesse

Tatu Portin said:
Size of char is _at least_ 1 byte.

Quote out of the C FAQ found in your sig (question 7.8):

"It's never necessary to multiply by sizeof(char), since sizeof(char)
is, by definition, exactly 1."

?
 
J

Jirka Klaue

Tatu Portin:
Sven Hesse:

Size of char is _at least_ 1 byte.

No!

6.5.3.4 The sizeof operator
2 The sizeof operator yields the size (in bytes) of its operand,
...
3 When applied to an operand that has type char, unsigned char,
or signed char, (or a qualified version thereof) the result is 1.

Jirka
 
M

Martin Ambuhl

Tatu said:
Size of char is _at least_ 1 byte.

This seems a perverse thing for you to have posted. Why did you not
include the equally true statement that sizeof(char) is _at most_ 1 byte?
 
P

pemo

Mockey Chen said:
My friend ask me a question as following:

give a union SU define as:
typedef union _SU
{
short x;
struct y{
char a;
short b;
char c;
};
}SU;

what is the sizeof (SU)?

My compiler tell me the answer is 6.
I want to know why the answer is 6.


Why not add another member and use that to 'explore' the other members,
e.g.,:

#include <stdio.h>

typedef union
{
int x;

struct
{
int a;
int b;
char c;
} y;

struct
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
unsigned char e;
unsigned char f;
} z;
}SU;

int main(void)
{
SU a;

printf("x = \t%p\n", &a.x);

printf("y.a = \t%p\n", &a.y.a);
printf("y.b = \t%p\n", &a.y.b);
printf("y.c = \t%p\n", &a.y.c);

printf("z.a = \t%p\n", &a.z.a);
printf("z.b = \t%p\n", &a.z.b);
printf("z.c = \t%p\n", &a.z.c);
printf("z.d = \t%p\n", &a.z.d);
printf("z.e = \t%p\n", &a.z.e);
printf("z.f = \t%p\n", &a.z.f);

return 0;
}
 
J

Jordan Abel

Why not add another member and use that to 'explore' the other members,
e.g.,:

[snipped]

Out of curiosity, why is it impossible to add a 'flexible array' to a
union? The best solution to this IMO would be an "unsigned char data[];"
member.
 
S

Skarmander

Jordan said:
Why not add another member and use that to 'explore' the other members,
e.g.,:

[snipped]

Out of curiosity, why is it impossible to add a 'flexible array' to a
union? The best solution to this IMO would be an "unsigned char data[];"
member.

Because that's pointless. If you want that, cast the address of the thing to
an unsigned char* and use that. Overloading flexible arrays for that isn't
worth it.

S.
 
F

Flash Gordon

pemo wrote:

<snip why is the size of a struct
Why not add another member and use that to 'explore' the other members,

Any results are highly implementation specific, of course.
e.g.,:

#include <stdio.h>

typedef union
{
int x;

struct
{
int a;
int b;

int main(void)
{
SU a;

printf("x = \t%p\n", &a.x);

If using %p you should cast the pointer to void*
printf("x = \t%p\n", (void*)&a.x);
printf("y.a = \t%p\n", &a.y.a);

Also, for this sort of thing using the offsetof macro from stddef.h
would be more useful.

<snip>
 
K

Keith Thompson

Mockey Chen said:
My friend ask me a question as following:

give a union SU define as:
typedef union _SU
{
short x;
struct y{
char a;
short b;
char c;
};
}SU;

what is the sizeof (SU)?

Please post real code. The union appears at first glance to have two
members, but you haven't actually declared the second member. You
have a struct declaration (I don't think that's even legal in this
context), but you haven't declared anything of that type.

Assuming that's corrected ...

sizeof(SU) is the number of bytes occupied by an object of type SU.
My compiler tell me the answer is 6.
I want to know why the answer is 6.

It happens to be 6 in the particular implementation you're using.
That's probably a very common result, but it's not required. Most
likely the union has the same size as its largest member, which is the
struct. It's certain that sizeof(char) is 1; it's likely that
sizeof(short) is 2, and that shorts require 2-byte alignment. Within
the struct, that puts "char a" at offset 0, "short b" at offset 2
(with a 1-byte gap for alignment), and "char c" at offset 4. An
additional 1-byte gap appears at the end of the structure so that the
b member within elements of an array of structures will be properly
aligned. This makes for a total of 6 bytes.

But the compiler is free to insert padding anywhere it likes (other
than at the beginning), and type short needn't necessarily be 2 bytes;
it could be 1 byte if CHAR_BIT is at least 16, and I've worked on
systems where sizeof(short)==8. Even assuming sizeof(short)==2, the
compiler might find it convenient to pad the structure (and therefore
the union) to 8 bytes and require 4-byte alignment.

Some more comments:

Don't use identifiers starting with an underscore. Some are reserved
to the implementation. The rule is more complicated than that,
depending on what follows the underscore, but the safest rule is to
avoid such identifiers altogether.

Using a typedef for a union or structure really isn't particularly
useful. Unless you're creating an abstract data type, where the code
using it shouldn't know that it's a union or structure, it's easier
just to use "struct foo" or "union bar". Your example could then be:

union SU {
short x;
struct {
char a;
short b;
char c;
} y;
};

(though all-caps identifiers are conventionally reserved for macro
names). Note that the struct type is anonymous; that's ok, since it
only appears as part of the union. Given
union SU obj;
you can then refer to
obj.x
obj.y.a
obj.y.b
obj.y.c
 
R

Robotnik

Keith said:
Please post real code. The union appears at first glance to have two
members, but you haven't actually declared the second member. You
have a struct declaration (I don't think that's even legal in this
context), but you haven't declared anything of that type.

Assuming that's corrected ...

sizeof(SU) is the number of bytes occupied by an object of type SU.


It happens to be 6 in the particular implementation you're using.
That's probably a very common result, but it's not required. Most
likely the union has the same size as its largest member, which is the
struct. It's certain that sizeof(char) is 1; it's likely that
sizeof(short) is 2, and that shorts require 2-byte alignment. Within
the struct, that puts "char a" at offset 0, "short b" at offset 2
(with a 1-byte gap for alignment), and "char c" at offset 4. An
additional 1-byte gap appears at the end of the structure so that the
b member within elements of an array of structures will be properly
aligned. This makes for a total of 6 bytes.

But the compiler is free to insert padding anywhere it likes (other
than at the beginning), and type short needn't necessarily be 2 bytes;
it could be 1 byte if CHAR_BIT is at least 16, and I've worked on
systems where sizeof(short)==8. Even assuming sizeof(short)==2, the
compiler might find it convenient to pad the structure (and therefore
the union) to 8 bytes and require 4-byte alignment.

Some more comments:

Don't use identifiers starting with an underscore. Some are reserved
to the implementation. The rule is more complicated than that,
depending on what follows the underscore, but the safest rule is to
avoid such identifiers altogether.

Using a typedef for a union or structure really isn't particularly
useful. Unless you're creating an abstract data type, where the code
using it shouldn't know that it's a union or structure, it's easier
just to use "struct foo" or "union bar". Your example could then be:

union SU {
short x;
struct {
char a;
short b;
char c;
} y;
};

(though all-caps identifiers are conventionally reserved for macro
names). Note that the struct type is anonymous; that's ok, since it
only appears as part of the union. Given
union SU obj;
you can then refer to
obj.x
obj.y.a
obj.y.b
obj.y.c

See the following link http://www.eskimo.com/~scs/C-faq/q2.13.html
 
T

Tim Rentsch

John Bode said:
The size of a union is the size of its largest member; in this case,
that would be struct y.

Often is but it doesn't have to be. Alignment requirements for
members, or alignment requirements imposed by the format of
pointer-to-union, can cause the size of a union to be larger than
the size of its largest member.
 

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

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top