• Advertisement

Archived

This topic is now archived and is closed to further replies.

A very basic question

This topic is 6518 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

What is this "__attribute__ ((packed))" thing in djgpp. I think it sqeezes things smaller, but I don''t know anything else about it. So what is it, what does it do and when should it be used?

Share this post


Link to post
Share on other sites
Advertisement
The current processors can only read from word-aligned addresses and read the full bus width at once. So Intel''s Pentiums read 32 bits (or 4 bytes) at once, from 32 bit aligned addresses (that is: 0, 4, 8, etc...). To read a single byte you need to do some extra calculations on the word you read (shifting and stuff).

So to speed things up a bit, the compiler makes sure that all variables are aligned at a 32 bit address. This means unfortunately that a char uses an equal amount memory as an int. If you use the ((packed)) attribute, you tell the compiler that he should not align the variables at 32 bit addresses, but instead pack them as tightly as possible. This uses much less memory, but is also slower. Normally, ((packed)) is only used for structs that are used for some kind of serialization (file or network I/O).

Hope this clears things up a bit.

Dormeur.

Share this post


Link to post
Share on other sites
I wasn''t aware of any compilers giving char variables the full 32-bits to ensure they have the correct alignment - after all, you''re gonna have to use some sort of internal masking to get at individual chars from any given 32 bits anyway. I was under the impression (and all my sizeof() studies confirm this for VC++) that the compiler merely made sure that variables do not cross alignment boundaries wherever possible so an int would be forced to align to 32-bit boundaries, but a char would be ok wherever.

One way you can help the compiler with this is by declaring variables in such an order that it will pack optimally - that is, declare chars in blocks of multiples of 4, rather than, for example, char/int/char/int which may waste 6 bytes in aligning the ints to the next boundary.

Share this post


Link to post
Share on other sites
I think you''re right: a char only takes up one byte, but the compiler will still make sure all ints are word-aligned. I guess the philosophy is to use ints as much as possible. No wonder the memory demands are going through the roof lately .
Anyway, I''ve tested it:

struct s1 {
char a,b,c,d;
int i;
};

sizeof(s1) = 8;

struct s2 {
char a,b;
int i;
char c,d;
};

sizeof(s2) = 12;

But (and this I don''t understand):

struct s3 {
char a;
union {
int i;
double d;
};
};

sizeof(s3) = 16; (!)

And I can''t explain this because a double takes up 8 bytes. Or have they changed it?

Dormeur.

Share this post


Link to post
Share on other sites
A double is still eight bytes.
The reason for the size of 16 is this:
The first byte is the char.
Then you have 7 bytes of padding.
Then you have your 8 bytes that are the union.

Why 7 bytes of padding?
Because Double is an 8 byte data type. The compiler is going to always try to optimize for the data types position unless overridden. In this case 8 byte fields starting on 8 byte boundary alignments.

Change the Double to a long and watch it go down to 12.

Share this post


Link to post
Share on other sites

  • Advertisement