Packed structs vs. unpacked structs: what's the difference?

D

Daniel Rudy

What is the difference between packed and unpacked structs?


--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fcsk more fcsk yes spray umount sleep
 
P

pemo

Daniel said:
What is the difference between packed and unpacked structs?


If you have gcc, try this - comment out/in the #pragma pack(1) line.

On my machine/implementation - with the pragma it outputs:

sizeof(s1) is 10, sizeof(s2) is 10

without the pragma:

sizeof(s1) is 16, sizeof(s2) is 12

Enough info for you to figure it out??


#include <stdio.h>
#pragma pack(1)

typedef struct struct_1
{
char a;
int b;
char c;
int d;

} s1;


typedef struct struct_2
{
char a;
char c;
int b;
int d;

} s2;


int main(void)
{
printf("sizeof(s1) is %d, sizeof(s2) is %d\n", sizeof(s1), sizeof(s2));

return 0;
}
 
R

Richard G. Riley

What is the difference between packed and unpacked structs?

One is packed and the other is, probably, not packed. The packed
keyword, to the best of my knowledge, overrides compiler optimisations
which lead to natural boundary alignment of one or more of the data
elements contained in the structure. A "packed" structure will almost
always have a smaller memory footprint than its unpacked brother.

See here: http://tinyurl.com/ftv3u

where there is a typically heated discussion on such issues.

I have no idea on the "standardness" of "packed". but here is another
article explaining it in the Gnu C environment:

http://grok2.tripod.com/structure_packing.html
 
N

Nick Keighley

pete said:
It's not standard C.

....and hence should be avoided if possible. "pragma pack" and their ilk
may slow your program at a slight saving in space and a loss of
portability.
 
S

slebetman

Nick said:
...and hence should be avoided if possible. "pragma pack" and their ilk
may slow your program at a slight saving in space and a loss of
portability.

Pragma pack is not often used to save space. Rather it is usually used
as a (non-portable) way to quickly "cast" a byte array (for example a
packet) into a struct. This way you can access data within the packet
directly by simply pointing the struct you want to the first byte of
the packet. This trick is very common in the majority of Unix TCP/IP
stack including Linux & BSD. It is also used in Windows TCP/IP stack
although Microsoft has a different syntax for their version of pragma
pack. But this, of course, is non-standard and is off topic to
comp.lang.c.
 
R

Richard G. Riley

...and hence should be avoided if possible. "pragma pack" and their ilk
may slow your program at a slight saving in space and a loss of
portability.

Pack is their for a reason : and not, I think, generally for saving
space. It is to enable a structure to correctly map to correct byte/word/etc
fields in protocol packets for example. Portability is not necessarily
an issue in these cases.
 
J

Jack Klein

If you have gcc, try this - comment out/in the #pragma pack(1) line.

On my machine/implementation - with the pragma it outputs:

sizeof(s1) is 10, sizeof(s2) is 10

without the pragma:

sizeof(s1) is 16, sizeof(s2) is 12

Enough info for you to figure it out??


#include <stdio.h>
#pragma pack(1)

typedef struct struct_1
{
char a;
int b;
char c;
int d;

} s1;


typedef struct struct_2
{
char a;
char c;
int b;
int d;

} s2;


int main(void)
{
printf("sizeof(s1) is %d, sizeof(s2) is %d\n", sizeof(s1), sizeof(s2));

This of course invokes undefined behavior twice, passing a size_t to
printf() with a conversion specifier of "%d". While the exact type of
size_t is implementation-defined, it is guaranteed never to be a
signed int.

Either cast to int with "%d", or, even better, cast to unsigned long
and use "%lu".

And yes, there are platforms where this will break, because size_t is
equivalent to unsigned long and long is physically larger than int.
 
C

CBFalconer

Jack said:
.... snip ...

This of course invokes undefined behavior twice, passing a size_t
to printf() with a conversion specifier of "%d". While the exact
type of size_t is implementation-defined, it is guaranteed never
to be a signed int.

Either cast to int with "%d", or, even better, cast to unsigned
long and use "%lu".

And yes, there are platforms where this will break, because size_t
is equivalent to unsigned long and long is physically larger than int.

The advantages of unbridled pedantry. The difference between
running and non-running code is one pedant.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
C

CBFalconer

Richard G. Riley said:
Pack is their for a reason : and not, I think, generally for
saving space. It is to enable a structure to correctly map to
correct byte/word/etc fields in protocol packets for example.
Portability is not necessarily an issue in these cases.

However it does nothing that cannot be done in a clean portable
manner with an array of unsigned char. Well beloved by Micro$loth
for its ability to lock code to proprietary systems.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
J

Jack Klein

The advantages of unbridled pedantry. The difference between
running and non-running code is one pedant.

Chuck, this time you've just gotten too obscure for me. Are you
agreeing with me, or with pemo?
 
C

CBFalconer

Jack said:
Chuck, this time you've just gotten too obscure for me. Are you
agreeing with me, or with pemo?

You :) And taking a dig at pemos sig. And creating a new measure.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
P

pemo

CBFalconer said:

Aw, that's a shame - for a second there I was thinking, that's one less of
them, and one more of us!
And taking a dig at pemos sig. And creating a new measure.

btw, *pemos* requires an apostrophe as it's /possessive/. Sorry - just a bit
picky on grammar :)
 
N

Nick Keighley

Richard said:
Pack is their for a reason : and not, I think, generally for saving
space. It is to enable a structure to correctly map to correct byte/word/etc
fields in protocol packets for example. Portability is not necessarily
an issue in these cases.

why is portability not an issue for protocol stacks?
 
S

slebetman

Nick said:
why is portability not an issue for protocol stacks?

Mainly because most things that can run TCP/IP will first make it a
priority to port gcc. So as long as the code is as portable as gcc is
it doesn't matter if other compilers can't use the code. Systems where
gcc is not appropriate, such as embedded microcontrollers, tend to also
be very resource constrained and requires a very different
implementation of the protocol stack anyway. Actually, IMHO, the number
one reason why the TCP/IP stack is written that way is historical. The
BSD stack was written that way and is considered by most in the
networking community as the canonical implementation. So you find that
the Linux and Windows TCP/IP stack are also written using this
nonstandard, nonportable* convention.

* Note: It's funny to call this nonstandard practice nonportable since
it has been ported to almost all existing OSes, Unix-like or otherwise.
The only stupid thing is that you have to do lots of #ifdef because
Microsoft's VC++ and gcc both have this feature but with different
syntax.
 
K

Keith Thompson

Nick said:
Richard G. Riley wrote: [...]
Pack is their for a reason : and not, I think, generally for
saving space. It is to enable a structure to correctly map to
correct byte/word/etc fields in protocol packets for
example. Portability is not necessarily an issue in these cases.

why is portability not an issue for protocol stacks?

Mainly because most things that can run TCP/IP will first make it a
priority to port gcc. So as long as the code is as portable as gcc is
it doesn't matter if other compilers can't use the code. Systems where
gcc is not appropriate, such as embedded microcontrollers, tend to also
be very resource constrained and requires a very different
implementation of the protocol stack anyway.
[...]

I've used Unix systems (Cray Unicos) to which gcc has not been ported,
and other systems (AIX, arguably Solaris) where the gcc implementation
is not nearly as good as the "native" C compiler (or so I've heard; I
haven't measured it myself).

I suspect that most packet layouts are such that ordinary structure
declarations will map to them correctly. The choice of types for the
members won't be portable of course, but if there are no gaps within
the packet layout, and all the components of the packet are properly
aligned relative to the start of the packet, packing shouldn't be
necessary. (I think.)
 

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,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top