In my previous post I was talking about memory alignment, and how the compiler can add padding to structures and classes. Sometimes you don’t want the extra padding, let’s say, because you are going to use the structure or class object as data header to be sent to the network. For simplicity sake let’s take the structure we saw in my previous post:
struct aligned { long long_data; char byte_data; int integer_data; };
Despite the fact that I would never send such structure by the network, since you never know wich computer architecture is going to receive the data, thus, you have to consider endianess and size of int’s etc, the important thing here is that with padding, that structure is likely to have a size of 12 bytes ( see previous post to know why ). If we want to avoid padding effects, and we are using GCC compiler, we can use packed attribute, like this:
struct aligned { long long_data; char byte_data; int integer_data; } __attribute__ ((packed));
Using sizeof() to check the size of such structure will show us that has the expected 9 bytes for x86 32 bit. Other compilers, like VisualStudio, might use the #pragma directive, not quite sure about how it is used there, but the effect is the same.
Packing a struct or class is easy, however, there are some considerations we should be aware of, let’s say we have this program:
#include <iostream> using namespace std; struct packedstruct { int integer; char byte; } __attribute__ ((packed)); void func(int &val) { cout << "calling func\n"; val += 10; } int main() { packedstruct mypackage; mypackage.integer = 10; func(mypackage.integer); cout << "val is " << mypackage.integer << "\n" << endl; return 0; }
What’s the problem with that? well, trying to compile that code, in recent GCC ( 4.1.0 ), will result in an error like this:
packed.cpp:20: error: cannot bind packed field ‘mypackage.packedstruct::integer’ to ‘int&’
It seems somehow representation of packed/unaligned data is not fully compatible with aligned data? We had this issue with some code, I have not understood yet what exactly means, but doing “const” the reference get rids of the issue, of course, if you really need the reference to be non const, how to proceed? I would like to know what is really going on here, if anyone out there knows, please let me know, I found this link, im still chewing that to understand the implications of what that guy says about the LSB … http://gcc.gnu.org/ml/gcc-patches/2003-07/msg01664.html