免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2424 | 回复: 9
打印 上一主题 下一主题

[C++] 求助:初学C++,一个关于struct变量大小的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-12-24 16:29 |只看该作者 |倒序浏览
程序如下:
#include<iostream.h>

struct employee{
    short int emplno;
    char name[20];
    float wage;
};

int main()
{
    employee emp={
        123,
        "andy",
        32.1
     };
    cout<<sizeof emp<<endl;
    return 0;
}

为什么最后输出结果是28?(XP SP2,C-FREE)
为什么不是2+20+4=26?难道是运行的时候将 short int 强制转换成了float?

论坛徽章:
0
2 [报告]
发表于 2006-12-24 16:33 |只看该作者
因为对齐。

论坛徽章:
0
3 [报告]
发表于 2006-12-24 16:37 |只看该作者
因为对齐??
不好意思,我是初学,LS说的对齐能不能稍微详细点 因为我这个实在没有老师教
非常感谢!!

论坛徽章:
0
4 [报告]
发表于 2006-12-24 16:39 |只看该作者
还是谢谢2楼的啊
我上百度搜索了下 学习ING

论坛徽章:
0
5 [报告]
发表于 2006-12-24 17:29 |只看该作者

再次求救

看了下网上的数据对齐 这个地方还是不太懂 希望各位热心的能帮忙解释下
如果有
#progma pack (4)
struct C { int a; short c; char b;};
cout<<sizeof(C);
结果为什么是8呢?
我是这样想的:假设C从0x0000开始那边a就应该放在0x0004,0x0005,0x0006,0x0007(符合0x0004%4=0)
然后c就是0x0008,0x0009(符合0x0008%2=0)
最后b就是0x0010(符合0x0010%1=0)
所以从0x0000到0x00010共11字节存放的是C的变量,又C的自身对齐值为4,所以C的有效对齐值为4
那么结果就应该是12 啊 怎么是8呢
估计是我的理解错误,希望各位高手帮忙解答下

论坛徽章:
0
6 [报告]
发表于 2006-12-24 17:32 |只看该作者
原帖由 jimodeduzou 于 2006-12-24 01:29 发表
看了下网上的数据对齐 这个地方还是不太懂 希望各位热心的能帮忙解释下
如果有
#progma pack (4)
struct C { int a; short c; char b;};
cout<<sizeof(C);
结果为什么是8呢?
我是这样想的:假设C从0 ...


a在结构C的起始地址,就是你说的0x00

论坛徽章:
0
7 [报告]
发表于 2006-12-24 17:38 |只看该作者
按照LS的意思就是
a放在0x0000,0x0001,0x0002,0x0003
c放在0x0004,0x0005
b放在0x0006
那么就是0x0000-0x0006 7个字节是C的变量
C的有效对齐值为4 那么最后的8就是这样来的

我这样理解没有错吧?
非常感谢你

论坛徽章:
0
8 [报告]
发表于 2006-12-24 17:41 |只看该作者
原帖由 jimodeduzou 于 2006-12-24 01:38 发表
按照LS的意思就是
a放在0x0000,0x0001,0x0002,0x0003
c放在0x0004,0x0005
b放在0x0006
那么就是0x0000-0x0006 7个字节是C的变量
C的有效对齐值为4 那么最后的8就是这样来的

我这样理解没有错吧?
非 ...


偶认为是酱紫的。

论坛徽章:
0
9 [报告]
发表于 2006-12-24 20:16 |只看该作者
关于struct的使用方法

struct是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如array、struct、union等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。

 自然对界是指按结构体的成员中size最大的成员对齐。



#pragma pack规定的对齐长度,实际使用的规则是:

结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和结构体的自然对齐长度中比较小的那个进行。

也就是说,当#pragma pack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。

结构体的对齐,按照结构体中size最大的数据成员和#pragma pack指定值之间,较小的那个进行。



具体解释

#pragma pack(4)

  class TestB

  {

  public:

    int aa; //第一个成员,放在[0,3]偏移的位置,

    char a; //第二个成员,自身长为1,#pragma pack(4),取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。

    short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。

    char c; //第四个,自身长为1,放在[8]的位置。

  };

这个类实际占据的内存空间是9字节

类之间的对齐,是按照类内部最大的成员的长度,和#pragma pack规定的值之中较小的一个对齐的。

所以这个例子中,类之间对齐的长度是min(sizeof(int),4),也就是4。

9按照4字节圆整的结果是12,所以sizeof(TestB)是12。



如果

#pragma pack(2)

    class TestB

  {

  public:

    int aa; //第一个成员,放在[0,3]偏移的位置,

    char a; //第二个成员,自身长为1,#pragma pack(4),取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。

    short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。

    char c; //第四个,自身长为1,放在[8]的位置。

  };

//可以看出,上面的位置完全没有变化,只是类之间改为按2字节对齐,9按2圆整的结果是10。

//所以 sizeof(TestB)是10。

最后看原贴:

现在去掉第一个成员变量为如下代码:

  #pragma pack(4)

  class TestC

  {

  public:

    char a;//第一个成员,放在[0]偏移的位置,

    short b;//第二个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[2,3]的位置。

    char c;//第三个,自身长为1,放在[4]的位置。

  };

//整个类的大小是5字节,按照min(sizeof(short),4)字节对齐,也就是2字节对齐,结果是6

//所以sizeof(TestC)是6。

在Linux下面就是

#define __PACKED_ATTR       __attribute__ ((__packed__))



typedef struct {

        char p[3] __PACKED_ATTR;

        long i __PACKED_ATTR;

} test ;



typedef struct {

        char p[3];

        long i;

} test1;



gcc test.c 编译后,它们的大小就是7,8了





windows下面默认的是#pragma pack(2)

因为编译器在编译时会对程序进行优化,以便加快访问速度,所以一般都会按照2的倍数进行字节对齐。用这个宏就是为了防止编译器对结构的定义进行对齐。

#pragma(push,n)用来设置警告消息的等级

论坛徽章:
0
10 [报告]
发表于 2006-12-25 13:06 |只看该作者
跟操作系统和硬件有关系吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP