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位系统下各数据类型占用字节统计如下:
具体字节对齐填充原理可以参考此连接:
原创文章,转载请注明出处!谢谢
本文来自博客园,作者:IT情深,转载请注明原文链接:https://www.cnblogs.com/wh445306/p/16751793.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?