What's this: __attribute__((packed))
I see some code about Hostap project,in these codes,I found some structure which have such signs: __attribute__((packed)),I don't know what does this mean. So soon I found more such signs in Linux Kernel Souce code.Who can tell me what does this mean exactly and how I use it?Thanks
|
Here is how I think it works (please correct me if I'm wrong!)
__attribute__((packed)) ensures that structure fields align on one-byte boundaries. If you want to ensure that your structures have the same size on all processors, the packed attribute is how you tell gcc. As an example, let's define this structure: Code:
struct s { A processor that aligns on four-byte boundaries may compile this so that aChar is in the first byte, followed by three bytes of unused space, then starting anInt in the fifth byte. To force anInt to begin immediately after aChar, you would define the structure like this: Code:
struct s { Code:
#include <stdio.h> Code:
eric.r.turner@turing:~/lab/packed$ ./foo |
thanks a lot!
|
But when I wirte the progarm like this:
struct s1 { void *a; char b[2]; int i; }; struct s2 { void *a char b[2]; int i ; }__attribute__((packed)); and got the result like this: sizeof s1 is 12 sizeof s2 is 10 WHY? I think sizeof s2 should be 11! |
Why would it be 11?
void *a => 32-bit processor means this is 32 bits wide (or 4 bytes) char b[2] => a char is typically 1 byte. You have two of them. So b occupies 2 bytes int i => most 32-bit machines also default to 32 bits for plain integers (again, 4 bytes) So sizeof(a) + sizeof(b) + sizeof(i) = 4 + 2 + 4 = 10 For your non-packed structure, you processor is aligning to 4-byte boundaries. Thus, a fills one full 4-byte block, b fills two bytes of the next block (leaving 2 other bytes unused), and i occupies the next full 4-byte block. So, in that case: sizeof(a) + sizeof(b) + sizeof(wasted space) + sizeof(i) = 4 + 2 + 2 + 4 = 12 |
thanks,I made a mistake.
|
struct s2 {
char a; int i __attribute__ ((packed)); char b; int i1; }; (on 32-bit machine) Its showing the size of this structure is 12. Can you plz tell me why ? |
Yup.. I found it..
Its allocating as follows, 1 byte + 4 bytes + 1 byte + 2 bytes + 4 bytes char a, int i, char b, zeroes, int i1 |
Quote:
|
I found this thread helpful. Thanks for the __attribute__ ((packed)) explaination.
|
hi ,
struct s2 { char a; int i __attribute__ ((packed)); char b; int i1; }; here sizeof(s2) = 12. But actually size should be 10 ( 1 byte+4 bytes + 1 byte + 4 bytes ),how ? how it would be ( 1 byte+4 bytes + 1 byte + 2 bytes + 4 bytes ) = sizeof(a)+ sizeof(i) +sizeof(b)+ 2 zeros + sizeof(i1)) here what is this another 2 bytes ( 2 zeros ) ? Can anyone ,please explain ? Thanks in advance . regards, Rajesh. |
You might want to use two packed's:
Code:
struct s2 { - is a non-standard extension - slows down the processing - should be avoided |
Quote:
|
it's four, actually, not eight
|
Why not use the pack pragma to set the alignment around the structure? IE:
Code:
#pragma pack(1) Whereas: Code:
|
Quote:
I don't remember the details well enough to repeat any of it convincingly, but I was convinced when I read it. In real projects, it is a lot easier to wrap __attribute__ into a preprocessor macro (to make it properly conditional on the compiler/architecture in a semi portable project) than to do that with #pragma Quote:
In the quoted code, the packed attribute applies only to i and not to i1 Other methods of specifying packed (appearing elsewhere in this thread) apply the packed attribute to the entire struct. Quote:
Quote:
Quote:
|
Quote:
--- rod. |
Code:
typedef struct network_format { |
I agree that your suggestion will probably work with respect to packing/alignment (most of your suggestion seems to relate to byte-ordering; a different but related subject) on most architectures, there is nothing to ensure that the packing of the structure will necessarily be the same as a deliberately packed structure. Without the directive not to, padding bytes may be added in any part of the struct. In practice, AFAIK, this would rarely be done between char type elements, but again, this is not guaranteed. Nested structures make the problem even more difficult.
If the solution comes down to breaking every structure element into its respective char-sized elements, then I see the solution as much worse than the problem. I would say that the __attribute__((packed)) directive preserves the purpose of the C struct, by allowing an expression that plainly reflects the nature of the data. Unfortunately, it forces us to know when it is necessary, and embeds architecture-specific features into our source code. --- rod. |
Sorry, from your answer I couldn't decide if my answer helped or not. Maybe I should summarize it in plain text: define a special structure only for the network traffic, in this structure every data-element that isn't aligned on its natural alignment (for elementary types it is an offset that is divisible with their size) are to be replaced with char-arrays. To convert from/to this special structure, you have to write conversion functions.
PS: The opposite problem may arise if the network protocol demands gaps between the fields that your compiler may or may not provide; you can add 'char unused_nnn [gapsize]' fields to be sure. PPS: And obviously types short/int/long long mustn't be used in the network structure, int16_t/int32_t/int64_t are you friends. |
All times are GMT -5. The time now is 07:10 AM. |