Windows 32、64位系统编译器各数据类型大小和字节对齐关系

何为32位64位?

32位64位其实就是32bit 64bit ,32位cpu单次处理指令4字节,64位8字节,因为1字节=1byte=8bit(32/8=4字节,64/8=8字节)

32位编译器:32位系统下指针占用4字节

64位编译器:64位系统下指针占用8字节

struct结构体成员中对齐关系:

字节对齐的细节和具体编译器实现相关,但一般而言,需满足以下四个准则:

1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;

2) 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;

3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。

4)结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储

 

随便贴几个32/64相同结构体字节对齐填充示例:

{32位}
_UNICODE_STRING = packed record
Length : USHORT;
MaximumLength : USHORT;
Buffer : PWideChar;
end;
UNICODE_STRING = _UNICODE_STRING;
PUNICODE_STRING =^_UNICODE_STRING;
{64位}
_UNICODE_STRING64 = packed record
Length : USHORT; //USHORT=2字节
MaximumLength : USHORT;
Fill : DWORD; //填充4字节对齐
Buffer : ULONG64;//ULONG64; //PVOID64
end;
UNICODE_STRING64 = _UNICODE_STRING64;
PUNICODE_STRING64 =^_UNICODE_STRING64;
{32位}
PLDR_DATA_TABLE_ENTRY = ^LDR_DATA_TABLE_ENTRY;
LDR_DATA_TABLE_ENTRY = packed Record
InLoadOrderModuleList:LIST_ENTRY;
InMemoryOrderModuleList:LIST_ENTRY;
InInitializationOrderModuleList:LIST_ENTRY;
BaseAddress:Cardinal;
EntryPoint:Cardinal;
SizeOfImage:Cardinal;
FullDllName:UNICODE_STRING;
BaseDllName:UNICODE_STRING;
Flags:Cardinal;
LoadCount:Word;
TlsIndex:Word;
SectionHandle:Cardinal;
CheckSum:Cardinal;
TimeDateStamp:Cardinal;
end;
{64位}
PLDR_DATA_TABLE_ENTRY64= ^LDR_DATA_TABLE_ENTRY64;
LDR_DATA_TABLE_ENTRY64 = packed record
InLoadOrderModuleList:LIST_ENTRY64;//PVOID64;//LIST_ENTRY;
InMemoryOrderModuleList:LIST_ENTRY64;//PVOID64;//LIST_ENTRY;
InInitializationOrderModuleList:LIST_ENTRY64;//PVOID64;//LIST_ENTRY;
BaseAddress:ULONG64;
EntryPoint:ULONG64;
SizeOfImage:ULONG64;//ULONG; //8字节对齐
FullDllName:UNICODE_STRING64;
BaseDllName:UNICODE_STRING64;
Flags:ULONG;
LoadCount:USHORT;
TlsIndex:USHORT;
end;
{32位}
PPEB_LDR_DATA =^PEB_LDR_DATA;
PEB_LDR_DATA = packed record
Len:Cardinal;
Initialized:Bool;
SsHandle:PPointer;
InLoadOrderModuleList:LIST_ENTRY;
InMemoryOrderModuleList:LIST_ENTRY;
InInitializationOrderModuleList:LIST_ENTRY;
end;
{64位}
PPEB_LDR_DATA64= ^PEB_LDR_DATA64;
PEB_LDR_DATA64 = packed record
Length:ULONG; //4Byte
Initialized:BOOLEAN; //1Byte
Reserved1: array [0..2] of Byte; //3Byte 补3字节填充跟前面一起凑成8字节
SsHandle:ULONG64; //8Byte
InLoadOrderModuleList:LIST_ENTRY64; // PVOID64
InMemoryOrderModuleList:LIST_ENTRY64;
InInitializationOrderModuleList:LIST_ENTRY64;
EntryInProgress:ULONG64;
end;
{32位}
PPEB = ^PEB;
PEB = packed record
Reserved1: array[0..1] of Byte;
BeingDebugged: ByteBool;
Reserved2: Byte;
Reserved3: array[0..1] of Pointer;
Ldr: PPEB_LDR_DATA; //Pointer
ProcessParameters: PRTL_USER_PROCESS_PARAMETERS;
Reserved4: array[0..103] of Byte;
Reserved5: array[0..51] of Pointer;
end;
{64位}
PPEB64 = ^PEB64;
PEB64 = packed record
InheritedAddressSpace : UCHAR; //1 Byte
ReadImageFileExecOptions : UCHAR;
BeingDebugged: UCHAR;
BitField: UCHAR;
Reserved1:DWORD; //因为64位系统是8字节对齐,所以补4位,跟前面4个uchar一起凑成8字节
Mutant:ULONG64; //编译器问题,VC++不用补位,实测VS2017,VS2015中编译器貌似会自动填充对齐
ImageBaseAddress: ULONG64;
Ldr:PVOID64; //PPEB_LDR_DATA64; //ULONG64;
ProcessParameters:PVOID64;//PRTL_USER_PROCESS_PARAMETERS64; // ULONG64;
SubSystemData: ULONG64;
ProcessHeap: ULONG64;
FastPebLock: ULONG64;
AtlThunkSListPtr:ULONG64;
IFEOKey: ULONG64;
CrossProcessFlags: ULONG64;
UserSharedInfoPtr: ULONG64;
SystemReserved: ULONG;
AtlThunkSListPtr32:ULONG;
ApiSetMap: ULONG64;
end;

Delphi中32位64位程序在64位系统下各数据类型占用字节统计如下:

 

具体字节对齐填充原理可以参考此连接:

32位源码编译64位程序时的字节对齐问题

原创文章,转载请注明出处!谢谢

posted @   IT情深  阅读(519)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示