什么时候用 packed record??

okmnji79513 2010-07-14 03:46:36
我在转换 C++的结构体:

#define RASDIALPARAMSA struct tagRASDIALPARAMSA
RASDIALPARAMSA
{
DWORD dwSize;
CHAR szEntryName[ 256 + 1 ];
CHAR szPhoneNumber[ 128 + 1 ];
CHAR szCallbackNumber[ 128 + 1 ];
CHAR szUserName[ 256 + 1 ];
CHAR szPassword[ 256 + 1 ];
CHAR szDomain[ 15 + 1 ];
};

本来是用的 packed record ,结果发现结构体长度不对。

于是,我手算了一下:一共占位 1049 (4+257+129+129+257+257+16) ,我的 "packed record" 也是 1049 ,应该对啊 ,感到奇怪。
于是,在 C++里 求了一下长度,是1052... 和 Delphi中 不用 "packed" 时的长度一样 ,VC6的编译器 和 Delphi6 一样做了对齐??

那我在 转结构体 的时候,如何知道什么时候应该使用 "packed" ??? 求解~!!!
...全文
179 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
okmnji79513 2010-07-14
  • 打赏
  • 举报
回复
OK,结贴
僵哥 2010-07-14
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 okmnji79513 的回复:]
引用 7 楼 unsigned 的回复:
纯单字节结构体就是一段内存,换句话说,你这个结构体与
char buff[256 + 1 + 128 +1 +128 +1 +256 +1 +256 +1 +15 +1];
这样子的定义没有任何差别。

那为什么不能认为:

C/C++ code

#define RASDIALPARAMSA struct tagRASDIALPARAM……
[/Quote]
你应该先了解一下内存字节对齐的初衷是什么。
okmnji79513 2010-07-14
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 unsigned 的回复:]
纯单字节结构体就是一段内存,换句话说,你这个结构体与
char buff[256 + 1 + 128 +1 +128 +1 +256 +1 +256 +1 +15 +1];
这样子的定义没有任何差别。
[/Quote]
那为什么不能认为:

#define RASDIALPARAMSA struct tagRASDIALPARAMSA
RASDIALPARAMSA
{
DWORD dwSize;
CHAR szEntryName[ 256 + 1 ];
CHAR szPhoneNumber[ 128 + 1 ];
CHAR szCallbackNumber[ 128 + 1 ];
CHAR szUserName[ 256 + 1 ];
CHAR szPassword[ 256 + 1 ];
CHAR szDomain[ 15 + 1 ];
};

是 : char buff[4 + 256 + 1 + 128 +1 +128 +1 +256 +1 +256 +1 +15 +1];
僵哥 2010-07-14
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 okmnji79513 的回复:]
同样 Delphi 中:

Delphi(Pascal) code

MyRec2=Record
var1:integer;
var2:array[0..6]of char;
end;

就是 12,而

Delphi(Pascal) code

MyRec2=Record
// var1:integer;
var2:arra……
[/Quote]
回复同#7楼。
僵哥 2010-07-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 gyk120 的回复:]
引用 4 楼 unsigned 的回复:
引用 2 楼 gyk120 的回复:
调用windows api或者其他语言开发的DLL时,为了便于对齐,要用packed

微软还是很注意这个问题的,基本上调用windows api需要使用packed的情况很少。通常microsoft定义的结构体当中,都会注意到这个问题,会为其添加reserved成员来补齐。

受教了
[/Quote]
呃... 别这么说,只是使用windows api的过程当中的一个总结。
okmnji79513 2010-07-14
  • 打赏
  • 举报
回复
同样 Delphi 中:

MyRec2=Record
var1:integer;
var2:array[0..6]of char;
end;

就是 12,而

MyRec2=Record
// var1:integer;
var2:array[0..6]of char;
end;

就是 7.

为什么 多了一个 integer 成员之后 ,结构体就需要对齐??
僵哥 2010-07-14
  • 打赏
  • 举报
回复
纯单字节结构体就是一段内存,换句话说,你这个结构体与
char buff[256 + 1 + 128 +1 +128 +1 +256 +1 +256 +1 +15 +1];
这样子的定义没有任何差别。
okmnji79513 2010-07-14
  • 打赏
  • 举报
回复
还是 不太明白:
为什么

#define RASDIALPARAMSA struct tagRASDIALPARAMSA
RASDIALPARAMSA
{
DWORD dwSize;
CHAR szEntryName[ 256 + 1 ];
CHAR szPhoneNumber[ 128 + 1 ];
CHAR szCallbackNumber[ 128 + 1 ];
CHAR szUserName[ 256 + 1 ];
CHAR szPassword[ 256 + 1 ];
CHAR szDomain[ 15 + 1 ];
};

是 1052 ,而 :

#define RASDIALPARAMSA struct tagRASDIALPARAMSA
RASDIALPARAMSA
{
// DWORD dwSize;
CHAR szEntryName[ 256 + 1 ];
CHAR szPhoneNumber[ 128 + 1 ];
CHAR szCallbackNumber[ 128 + 1 ];
CHAR szUserName[ 256 + 1 ];
CHAR szPassword[ 256 + 1 ];
CHAR szDomain[ 15 + 1 ];
};

是 1045 ??? 多了一个 DWORD ,为什么就要多 3位??
gyk120 2010-07-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 unsigned 的回复:]
引用 2 楼 gyk120 的回复:
调用windows api或者其他语言开发的DLL时,为了便于对齐,要用packed

微软还是很注意这个问题的,基本上调用windows api需要使用packed的情况很少。通常microsoft定义的结构体当中,都会注意到这个问题,会为其添加reserved成员来补齐。
[/Quote]
受教了
僵哥 2010-07-14
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 gyk120 的回复:]
调用windows api或者其他语言开发的DLL时,为了便于对齐,要用packed
[/Quote]
微软还是很注意这个问题的,基本上调用windows api需要使用packed的情况很少。通常microsoft定义的结构体当中,都会注意到这个问题,会为其添加reserved成员来补齐。
僵哥 2010-07-14
  • 打赏
  • 举报
回复

#define RASDIALPARAMSA struct tagRASDIALPARAMSA
RASDIALPARAMSA
{
DWORD dwSize;
CHAR szEntryName[ 256 + 1 ];
CHAR szPhoneNumber[ 128 + 1 ];
CHAR szCallbackNumber[ 128 + 1 ];
CHAR szUserName[ 256 + 1 ];
CHAR szPassword[ 256 + 1 ];
CHAR szDomain[ 15 + 1 ];
};

当成
#define RASDIALPARAMSA struct tagRASDIALPARAMSA
RASDIALPARAMSA
{
DWORD dwSize;
CHAR szEntryName[ 256 + 1 ];
CHAR szPhoneNumber[ 128 + 1 ];
CHAR szCallbackNumber[ 128 + 1 ];
CHAR szUserName[ 256 + 1 ];
CHAR szPassword[ 256 + 1 ];
CHAR szDomain[ 15 + 1 ];
CHAR szReserved[ 3 ];
};

这样子,不管你使用的是四字节对齐,还是单字节对齐都没有差异。
gyk120 2010-07-14
  • 打赏
  • 举报
回复
调用windows api或者其他语言开发的DLL时,为了便于对齐,要用packed
僵哥 2010-07-14
  • 打赏
  • 举报
回复
delphi 当中使用packed,即为按单字节对齐
相当于c++里面使用了
#pragma pack(1)
...//结构体定义
#pragma pop()
//获得硬盘序列号 function GetIdeSerialNumber: pchar; const IDENTIFY_BUFFER_SIZE = 512; type TIDERegs = packed record bFeaturesReg: BYTE; // Used for specifying SMART "commands". bSectorCountReg: BYTE; // IDE sector count register bSectorNumberReg: BYTE; // IDE sector number register bCylLowReg: BYTE; // IDE low order cylinder value bCylHighReg: BYTE; // IDE high order cylinder value bDriveHeadReg: BYTE; // IDE drive/head register bCommandReg: BYTE; // Actual IDE command. bReserved: BYTE; // reserved for future use. Must be zero. end; TSendCmdInParams = packed record // Buffer size in bytes cBufferSize: DWORD; // Structure with drive register values. irDriveRegs: TIDERegs; // Physical drive number to send command to (0,1,2,3). bDriveNumber: BYTE; bReserved: array[0..2] of Byte; dwReserved: array[0..3] of DWORD; bBuffer: array[0..0] of Byte; // Input buffer. end; TIdSector = packed record wGenConfig: Word; wNumCyls: Word; wReserved: Word; wNumHeads: Word; wBytesPerTrack: Word; wBytesPerSector: Word; wSectorsPerTrack: Word; wVendorUnique: array[0..2] of Word; sSerialNumber: array[0..19] of CHAR; wBufferType: Word; wBufferSize: Word; wECCSize: Word; sFirmwareRev: array[0..7] of Char; sModelNumber: array[0..39] of Char; wMoreVendorUnique: Word; wDoubleWordIO: Word; wCapabilities: Word; wReserved1: Word; wPIOTiming: Word; wDMATiming: Word; wBS: Word; wNumCurrentCyls: Word; wNumCurrentHeads: Word; wNumCurrentSectorsPerTrack: Word; ulCurrentSectorCapacity: DWORD; wMultSectorStuff: Word; ulTotalAddressableSectors: DWORD; wSingleWordDMA: Word; wMultiWordDMA: Word; bReserved: array[0..127] of BYTE; end; PIdSector = ^TIdSector; TDriverStatus = packed record // 驱动器返回的错误代码,无错则返回0 bDriverError: Byte; // IDE出错寄存器的内容,只有当bDriverError 为 SMART_IDE_ERROR 时有效 bIDEStatus: Byte; bReserved: array[0..1] of Byte; dwReserved: array[0..1] of DWORD; end; TSendCmdOutParams = packed record // bBuffer的大小 cBufferSize: DWORD; // 驱动器状态 DriverStatus: TDriverStatus; // 用于保存从驱动器读出的数据的缓冲区,实际长度由cBufferSize决定 bBuffer: array[0..0] of BYTE; end;

16,743

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧