Clone existing structs with different alignment in Visual C++
Is there a way to clone an existing struct with different member alignment in Visual C++?
Here is the background:
I use an 3rd-party library, which defines several structs. To fill up the structs, I pass the address of the struct instances to some functions. Unfortunately, the functions only returns unaligned buffer, so that data of some members are always wrong.
/Zp is out of choice, since it breaks the other parts of the program. I know #pragma pack
modifies the alignment of the following de开发者_JAVA百科fined struct, but I would rather avoid copying the structs into my code, for the definitions in the library might change in the future.
Sample code:
library.h:
struct am_aligned { BYTE data1[10]; ULONG data2; }; struct untouched { BYTE data1[9]; int data2; };
test.cpp:
#include "library.h" // typedef alignment(1) struct am_aligned am_unaligned; int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { char buffer[20] = {}; for (int i = 0; i < sizeof(am_unaligned); i++) { buffer[i] = i; } am_aligned instance = *(am_aligned*) buffer; untouched useless; return 0; }
am_unaligned
is my custom declaration, and only effective in test.cpp
. The commented line does not work of course. untouched should still has the default alignment.
instance.data2
is 0x0f0e0d0c
, while 0x0d0c0b0a
is desired.
Thanks for help!
You should use #pragma pack
before including the headers of the library you use (and after, with push and pop). This way you won't have to define the structs by yourself.
#pragma pack(push, 1)
#include <libraryheader.h>
#pragma pack(pop)
// You can now use the struct defined in the library
Indeed, the library has been compiled using a given alignment. You cannot change this, it is already hard-coded in the binary compiled library. However, you have to instruct the compiler, when you compile your files, that the structs contained in the library, are to be defined and used with another alignment.
Not sure, maybe __declspec(align( number )) struct{...} will help. More on MSDN
I suspect the only problem is probably with the starting address of the buffer on stack that is not aligned.
Just providing an aligned buffer instead of a non aligned one should do the trick.
Several easy ways to do it:
- malloc the buffer as mallocated address are ok for any alignment.
- define your buffer as a buffer of long, it will be aligned (and copy using memcpy instead of for loop with cast to char *, it is faster anyway).
精彩评论