So, I’m coding some packet structures (Ethernet, IP, etc) and noticed that some of them are followed by attribute((packed)) which prevents the gcc compiler from attempting to add padding to them. This makes sense, because these structures are supposed to go onto the wire.
But then, I counted the words:
struct ether_header
{
u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */
u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */
u_int16_t ether_type; /* packet type ID field */
} __attribute__ ((packed));
This is copied from a site, but my code also uses 2 uint8_t and 1 uint16_t. This adds up to two words (4 bytes).
Depending on the source, the system prefers that structures be aligned according to multiples of 4,8, or even 16 bits. So, I don’t see why the attribute((packed)) is necessary, as afaik this shouldn’t get packed.
Also, why the double brackets ((packed)) why not use one pair?
If your structure is already a multiple of the right size, then no, the
__attribute__((packed))isn’t strictly necessary, but it’s still a good idea, in case your structure size ever changes for any reason. If you add/delete fields, or changeETH_ALEN, you’ll still want__attribute__((packed)).I believe the double parentheses are needed to make it easy to make your code compatible with non-gcc compilers. By using them, you can then just do this:
And then all attributes that you specify will disappear. The extra parentheses mean there is only one argument passed to the macro (instead of one or more), regardless of how many attributes you specify, and your compiler does not need to support variadic macros.