blue
驱动大牛
驱动大牛
  • 注册日期2001-04-25
  • 最后登录2010-10-15
  • 粉丝0
  • 关注0
  • 积分55分
  • 威望12点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
阅读:1706回复:9

关于C语言中的结构体嵌套

楼主#
更多 发布于:2002-06-27 10:35
有这样两个结构体:
typedef struct tagDATETIME
{
    WORD year; // Year
    WORD month; // Month (1 = Jan., 2 =Feb., … )
    WORD day; // Day of the month
    WORD hour; // Hour  
    WORD minute; // Minute
    WORD second; // Second
} DATETIME,*PDATETIME;

typedef struct tagUSERINFO
{
    WORD ICID;
    DATETIME MakeTime; //制卡时间,
    DWORD UserID;
    BYTE Right;
    BYTE Reserved[13]; //保留,未来使用
    BYTE R[16] ; //认证随机串
} USERINFO,*PUSERINFO;

这里我认为 USERINFO 这个结构体的长度为 48 Bytes,但实际在程序中 sizeof(USERINFO)=52,其中在MakeTime后多出两个字节,在R后多出两个字节。但sizeof(DATETIME)=12。
谁知道这多出的两个字节是作什么用的,检验和?谭浩强的《C语言设计》中没有讲到嘛!

最新喜欢:

feihuifeihui fly_flyfly_fl...
pjf
pjf
驱动中牛
驱动中牛
  • 注册日期2001-07-08
  • 最后登录2006-10-23
  • 粉丝0
  • 关注0
  • 积分42分
  • 威望4点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-06-27 11:09
你再看看:
#include<stdio.h>
#include<windows.h>
#pragma pack(push,1)
typedef struct tagDATETIME
{
WORD year; // Year
WORD month; // Month (1 = Jan., 2 =Feb., … )
WORD day; // Day of the month
WORD hour; // Hour
WORD minute; // Minute
WORD second; // Second
} DATETIME,*PDATETIME;

typedef struct tagUSERINFO
{
WORD ICID;
DATETIME MakeTime; //制卡时间,
DWORD UserID;
BYTE Right;
BYTE Reserved[13]; //保留,未来使用
BYTE R[16] ; //认证随机串
} USERINFO,*PUSERINFO;
#pragma pack(pop)

void main()
{
printf(\"%d\",sizeof(USERINFO));
}

那只是为了对齐。
fulminate
驱动小牛
驱动小牛
  • 注册日期2002-05-16
  • 最后登录2006-11-27
  • 粉丝0
  • 关注0
  • 积分19分
  • 威望2点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-06-27 11:32
#pragma pack(push,1) 有什么作用?
==========腾蛟起凤,孟学士之词宗;紫电青霜,王将军之武库==========
pjf
pjf
驱动中牛
驱动中牛
  • 注册日期2001-07-08
  • 最后登录2006-10-23
  • 粉丝0
  • 关注0
  • 积分42分
  • 威望4点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-06-27 12:02
1、保存以前对齐规则以便恢复。
2、设字节对齐,不再为DWORD
thundersp
驱动牛犊
驱动牛犊
  • 注册日期2002-03-11
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-06-27 12:28
内存排布的单位是什么呀?
tigerzd
驱动老牛
驱动老牛
  • 注册日期2001-08-25
  • 最后登录2004-12-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-06-27 12:54
这是MSDN中编译的/Zp选项的解释,就是设置Struct 结构的对齐方式。还有#pragma pack的解释。

/Zp   (Struct Member Alignment)
Home |  Overview |  How Do I |  Compiler Options

The Struct Member Alignment (/Zpn) option controls how the members of a structure are packed into memory and specifies the same packing for all structures in a module. When you specify this option, each structure member after the first is stored on either the size of the member type or n-byte boundaries (where n is 1, 2, 4, 8, or 16), whichever is smaller.

You should not use this option unless you have specific alignment requirements.

Command Line Project Settings Result
/Zp1 1 Byte Packs structures on 1-byte boundaries
/Zp2 2 Bytes Packs structures on 2-byte boundaries
/Zp4 4 Bytes Packs structures on 4-byte boundaries
/Zp8 8 Bytes Packs structures on 8-byte boundaries  (default)
/Zp16 16 Bytes Packs structures on 16-byte boundaries
/Zp Not applicable Specifies the same packing for all structures in a module.  


To find this option in the development environment, click Settings on the Project menu. Then click the C/C++ tab, and click Code Generation in the Category box.

You can also use #pragma pack to control structure packing.

#pragma pack( [ n] )

Specifies packing alignment for structure and union members. Whereas the packing alignment of structures and unions is set for an entire translation unit by the /Zp option, the packing alignment is set at the data-declaration level by the pack pragma. The pragma takes effect at the first structure or union declaration after the pragma is seen; the pragma has no effect on definitions.

When you use #pragma pack(n), where n is 1, 2, 4, 8, or 16, each structure member after the first is stored on the smaller member type or n-byte boundaries. If you use #pragma pack without an argument, structure members are packed to the value specified by /Zp. The default /Zp packing size is /Zp8.

The compiler also supports the following enhanced syntax:

#pragma pack( [ [ { push | pop}, ] [  identifier, ] ] [ n ] )

This syntax allows you to combine program components into a single translation unit if the different components use pack pragmas to specify different packing alignments.

Each occurrence of a pack pragma with a push argument stores the current packing alignment on an internal compiler stack. The pragma’s argument list is read from left to right. If you use push, the current packing value is stored. If you provide a value for n, that value becomes the new packing value. If you specify an identifier, a name of your choosing, the identifier is associated with the new packing value.

Each occurrence of a pack pragma with a pop argument retrieves the value at the top of an internal compiler stack and makes that value the new packing alignment. If you use pop and the internal compiler stack is empty, the alignment value is that set from the command-line and a warning is issued. If you use pop and specify a value for n, that value becomes the new packing value. If you use pop and specify an identifier, all values stored on the stack are removed from the stack until a matching identifier is found. The packing value associated with the identifier is also removed from the stack and the packing value that existed just before the identifier was pushed becomes the new packing value. If no matching identifier is found, the packing value set from the command line is used and a level-one warning is issued. The default packing alignment is 8.

The new, enhanced functionality of the pack pragma allows you to write header files that ensure that packing values are the same before and after the header file is encountered:

/* File name: include1.h
*/
#pragma pack( push, enter_include1 )
/* Your include-file code ... */
#pragma pack( pop, enter_include1 )
/* End of include1.h */

In the previous example, the current pack value is associated with the identifier enter_include1 and pushed, remembered, on entry to the header file. The pack pragma at the end of the header file removes all intervening pack values that may have occurred in the header file and removes the pack value associated with enter_include1. The header file thus ensures that the pack value is the same before and after the header file.

The new functionality also allows you to use code, such as header files, that uses pack pragmas to set packing alignments that differ from the packing value set in your code:

#pragma pack( push, before_include1 )
#include \"include1.h\"
#pragma pack( pop, before_include1 )

In the previous example, your code is protected from any changes to the packing value that might occur in include.h.

犯强汉者,虽远必诛! [img]http://www.driverdevelop.com/forum/upload/tigerzd/2002-12-13_sf10.JPG[/img]
pjf
pjf
驱动中牛
驱动中牛
  • 注册日期2001-07-08
  • 最后登录2006-10-23
  • 粉丝0
  • 关注0
  • 积分42分
  • 威望4点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-06-27 12:54
内存排布的单位是什么呀?
---------------------------------------------------------------------------------
你看呢
arthurtu
驱动巨牛
驱动巨牛
  • 注册日期2001-11-08
  • 最后登录2020-12-19
  • 粉丝0
  • 关注0
  • 积分26分
  • 威望161点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
  • 社区居民
7楼#
发布于:2002-06-27 13:22
呵呵。

都是VC惹的祸。
blue
驱动大牛
驱动大牛
  • 注册日期2001-04-25
  • 最后登录2010-10-15
  • 粉丝0
  • 关注0
  • 积分55分
  • 威望12点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-06-28 11:27
谢谢各位,放分!
不过,这倒不是VC的问题,而是Ansi C的问题,但不知是出于什么考虑才定的这个。
yufei_lgq
驱动牛犊
驱动牛犊
  • 注册日期2001-12-22
  • 最后登录2004-10-20
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2002-06-28 14:30
学习之中
游客

返回顶部