| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1832 人关注过本帖, 2 人收藏
标题:一个关于struct字节对齐的问题
只看楼主 加入收藏
myseemylife
Rank: 2
等 级:论坛游民
帖 子:100
专家分:58
注 册:2009-3-22
结帖率:91.67%
收藏(2)
已结贴  问题点数:20 回复次数:9 
一个关于struct字节对齐的问题
struct STUDENT
{
    char name[10];
    char sex;
    int age;
    char grade[10];
};
对于如上结构体。vc6.0下sizeof()的结果是28,我跟踪看内存中name和sex一起时12字节,age4字节,grade12字节,为什么内存中是这么放呢?
搜索更多相关主题的帖子: 内存 结构体 
2011-06-27 16:26
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:5 
程序代码:
#include <stdio.h>
#define BYTE_WIDTH 8

struct STUDENT {
    char name[10];
    char sex;
    int age;
    char grade[10];
};

char * to_binary_string(char ch, char * str) {
    int i, j;
    for(i = BYTE_WIDTH - 1, j = 0; i > -1; i--, j++)
        str[j] = ((ch >> i) & 1) + '0';
    str[j] = '\0';
    return str;
}

int main() {
    struct STUDENT john = {"john", 'l', 16, "v1"};
    char * p1 = (char *)&john, * p2 = p1;
    char str[BYTE_WIDTH + 1];
    while(p1 < p2 + sizeof(john)) {
        printf("%p: %s\n", p1, to_binary_string(*(char *)p1, str));
        p1++;
    }
    return 0;
}
/* Output:
0022FEEC: 01101010
0022FEED: 01101111
0022FEEE: 01101000
0022FEEF: 01101110
0022FEF0: 00000000
0022FEF1: 00000000
0022FEF2: 00000000
0022FEF3: 00000000
0022FEF4: 00000000
0022FEF5: 00000000
0022FEF6: 01101100
0022FEF7: 00000000
0022FEF8: 00010000
0022FEF9: 00000000
0022FEFA: 00000000
0022FEFB: 00000000
0022FEFC: 01110110
0022FEFD: 00110001
0022FEFE: 00000000
0022FEFF: 00000000
0022FF00: 00000000
0022FF01: 00000000
0022FF02: 00000000
0022FF03: 00000000
0022FF04: 00000000
0022FF05: 00000000
0022FF06: 00000000
0022FF07: 00000000

Process returned 0 (0x0)   execution time : 0.040 s
Press any key to continue.
*/


这个程序把该结构体对象在内存中的二进制打印了出来,你可以用它去分析一下,我就不想分析了。

sex域应该定义为char[2],汉字占两个字节。

[ 本帖最后由 lz1091914999 于 2011-6-27 18:39 编辑 ]

My life is brilliant
2011-06-27 18:36
njkido
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
帖 子:224
专家分:1184
注 册:2011-3-8
收藏
得分:0 
4字节对齐

4byte = 32bit

提高32位cpu读取内存效率
2011-06-27 18:38
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
回复 3楼 njkido
但是有不同类型的域,如果是intel的CPU,应该采用的是little endian。

My life is brilliant
2011-06-27 18:42
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
如果每个域之间都没有间隔那么在32位机中:char[10] + char + int + char[10] = 10 + 1 + 4 + 10 = 25字节,从结果很明显可以看出在sex域和age域之间隔了一个字节,在grade域的后面还多了2个字节,所以加起来就是28个字节。这里就不明白为什么编译器要这样去分配内存,有没有哪位前辈能解释下??

My life is brilliant
2011-06-27 19:09
njkido
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
帖 子:224
专家分:1184
注 册:2011-3-8
收藏
得分:0 
name是char 分配10字节 sex起始地址能被1整除,ok; total=10;
 
sex是char,分配1字节,age起始地址11,不能被4整除,补1个到12;total=12;

age是int,分配4字节,grade起始地址是16,能被1整除,ok;total=16;

grade是char,分配10字节,下一个地址是26,没有数据就必须保证地址在4字节整数倍上,补到28; total=28;

分配顺序是: 10+2+4+12 = 28

我的理解~
2011-06-27 19:51
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
程序代码:
#include <iostream>
#include <cstring>
#define BYTE_WIDTH 8

class Student {
private:
    char name[10];
    char sex;
    int age;
    char grade[10];
public:
    Student() {
        using std::strcpy;
        strcpy(name, "john");
        sex = 'l';
        age = 16;
        strcpy(grade, "v1");
    }
    ~Student() {}
    char * to_binary_string(int offset, char * str) {
        char * p = (char *)this + offset;
        for(int i = BYTE_WIDTH - 1, j = 0; i > -1; i--, j++)
            str[j] = ((*p >> i) & 1) + '0';
        str[BYTE_WIDTH] = '\0';
        return str;
    }
};


int main() {
    using std::cout;
    using std::endl;
    Student john;
    char str[BYTE_WIDTH + 1], * p = (char *)&john;
    cout << "sizeof(Student) : " << sizeof(Student) << endl;
    for(int i = 0; i < sizeof(john); i++)
        cout << (void *)p << ": " << john.to_binary_string(i, str) << endl;
    return 0;
}
/*  Output:
sizeof(Student) : 28
0x22feec: 01101010
0x22feec: 01101111
0x22feec: 01101000
0x22feec: 01101110
0x22feec: 00000000
0x22feec: 10001100
0x22feec: 11111011
0x22feec: 01110101
0x22feec: 11110100
0x22feec: 11010110
0x22feec: 01101100
0x22feec: 10000001
0x22feec: 00010000
0x22feec: 00000000
0x22feec: 00000000
0x22feec: 00000000
0x22feec: 01110110
0x22feec: 00110001
0x22feec: 00000000
0x22feec: 01110101
0x22feec: 10111100
0x22feec: 01011011
0x22feec: 11111111
0x22feec: 01110101
0x22feec: 01010000
0x22feec: 00110100
0x22feec: 01000001
0x22feec: 00000000

Process returned 0 (0x0)   execution time : 0.078 s
Press any key to continue.
*/


C++,对此做法也是一样的,也许就是6L说的那样。

My life is brilliant
2011-06-27 21:20
bccn_1234
Rank: 2
等 级:论坛游民
帖 子:22
专家分:13
注 册:2011-6-11
收藏
得分:0 
vc6:alt+F7->c/c++->code generation->struct member alignment
#pragma pack(n)
非常2的问题
2011-06-27 22:24
loveshuang
Rank: 9Rank: 9Rank: 9
来 自:湖北武汉
等 级:蜘蛛侠
帖 子:270
专家分:1198
注 册:2010-11-14
收藏
得分:0 
           这个结构体在VC中一般是以最大的那个类型内存分配的,在你写的那个里面就是一次给4个字节,所以char name[10]就得分配4个int型大小就是12个字节,这个是字节对齐的问题。按最大分配原则。菜鸟级回答仅供参加。。。
2011-06-27 22:57
kelas
Rank: 6Rank: 6
等 级:侠之大者
帖 子:176
专家分:434
注 册:2010-5-28
收藏
得分:15 
字节对齐的细节和编译器实现相关,但一般而言,满足三个准则: 1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除; 2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding); 3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
2011-06-28 09:58
快速回复:一个关于struct字节对齐的问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.097887 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved