在C和C ++中,我们被教会将结构填充视为特定于编译器,因此我们避免依赖序列化等事情。
另一方面,每当我们链接到第三方动态库或共享对象时,我们都依赖于一致的结构填充。
我们来自<windows.h>
:
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
HANDLE WINAPI CreateThread(
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt_ LPVOID lpParameter,
_In_ DWORD dwCreationFlags,
_Out_opt_ LPDWORD lpThreadId
);
我们不应该关心使用哪个编译器来创建Kernel32.dll,但是编译器定义的结构填充意味着如果使用了不同的编译器,那么Kernel32.dll可能会取消引用_SECURITY_ATTRIBUTES
指针与我们的应用程序包装它的方式不同。
LoadLibrary
或dlopen
),相同的基本原理是否有效? #pragma pack
,所有这些问题都会消失吗? #pragma pack
会成为结构序列化的可靠解决方案吗?答案 0 :(得分:2)
从语言角度来看,你是完全正确的。填充和结构布局是一个实现细节,编译器可以自由选择。
但实际上,要使编译器在任何特定平台上都有用,它必须遵循平台ABI。如果有人试图生成一个不遵守平台ABI的编译器,那将完全没用。
因此,您可以安全地假设您使用的任何编译器都将与平台ABI兼容。你找不到任何可行的编译器。