字节对齐 订阅
字节(Byte)是计算机信息技术用于计量存储容量和传输容量的一种计量单位,一个字节等于8位二进制数,在UTF-8编码中,一个英文字符等于一个字节。字节按照一定规则在空间上排列就是字节对齐。 展开全文
字节(Byte)是计算机信息技术用于计量存储容量和传输容量的一种计量单位,一个字节等于8位二进制数,在UTF-8编码中,一个英文字符等于一个字节。字节按照一定规则在空间上排列就是字节对齐。
信息
外文名
Byte aligned
拼    音
zi jie dui qi
相关领域
计算机信息技术
释    义
字节按照一定规则在空间上排列
中文名
字节对齐
性    质
一种计量单位
字节对齐解释
现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
收起全文
精华内容
下载资源
问答
  • 字节对齐

    2017-01-11 15:59:26
    字节对齐

    字节对齐

    标签: 嵌入式开发

    1、为什么要字节对齐

    结论:为了提高数据传递的效率。

    芯片内核和存储芯片之间通过控制总线来控制存储芯片的行为,通过地址总线告诉存储芯片地址,通过数据总线来传递数据。

    假设8位机,即数据总线是8bits,假设地址总线也是8bits。
    考察程序1:

    char test;
    test='a';
    test++;

    第一句定义char类型变量test,编译器会给test分配一个内存地址,假设是0x10。
    第二句,向0x10这个地址写入’a’对应的ASCII码。
    第三句,从0x10这个地址读出数据,加1后写回0x10。
    一个指令周期就可以完成读或者写操作。

    考察程序2:

    int num;
    num=1;
    num++;

    第一句定义int类型变量num,编译器会给num分配内存地址。假设int 2个字节长度,那么假设分配的地址就是0x10,0x11。
    第二句,假设我们采用大端模式存储,地址0x10写入0x00,地址0x11写入0x01。
    第三句,数据总线第一次读出地址0x10的数据0x00,放到寄存器R0;第二次读出地址0x11的数据0x01,放到寄存器R1;然后R1+1;并将R0、R1的值写回地址0x10、0x11。
    因为这是个8位机,数据总线8bits,一次只能读一个字节的数据,所以读或者写int类型的数据的话需要两个指令周期。

    再来看看16位机,数据总线16bits,假设地址总线也是16bits。
    地址总线多了,可寻址的空间大了;数据总线多了,一个字节还是8bits,剩下的8bits的数据线也不能闲着,来传递下一个地址的8bits数据。
    对于考察程序1,假设分配到0x0010地址,情况和8位机类似,一个指令周期就可以完成对char类型数据的读或者写工作。
    对于考察程序2,假设分配到0x0010,0x0011地址,0x0010存放0x00,0x0011存放0x01。当对int数据进行读取的时候,地址总线是0x0010,数据总线读的是地址0x0010的8bits数据外加地址0x0011的8bits数据。所以一个指令周期就可以完成对16bits的数据读或者写。
    对于考察程序2,如果编译器给分配地址是0x0011和0x0012怎么办?那么如果想读取这个int类型的数据怎么办?对不起,得两个指令周期:首先,地址总线写0x0010,数据总线读取地址0x0010和地址0x0011;然后,地址总线写0x0012,数据总线读取地址0x0012和地址0x0013。然后我们要的是0x0011和0x0012的数据。
    如果我还想一个指令周期读这些数据怎么办?那就需要字节对齐:对于int型数据,分配内存空间的时候要分配到0x0010、0x0012这种地址上面,不能分配到0x0011、0x0013这种地址上面,也就是分配到2的整数倍的地址上面。

    对于32位机,也是类似的情形。一次可以访问4个字节的数据。地址总线上面写0x00000000,数据总线会把0x00000000,0x00000001,0x00000002,0x00000003一共32bits的数据读回来。所以如果有一个4字节的数据,那么最好存储的时候4字节对齐,也就是分配到4的整数倍的地址上面。
    可能有人会想,我地址总线上面写0x00000001不行么,这样的话不就可以访问从01到04的数据,就可以不对齐了么?但这个是由硬件决定的,硬件上不允许这么写。

    同理,对于64位机,需要8字节对齐。

    2、字节对齐规则

    一般在编写程序的时候,不会指定变量存放在内存中的地址,因为编译器连接器会遵循字节对齐的原则,分配好地址。以32位机为例,1字节长度的变量分配到1的整数倍的地址,2字节长度的变量分配到2的整数倍的地址,4字节长度的变量分配到4的整数倍的地址。
    共用体union的长度是里面最大的变量长度的整数倍。例如:

    union tagA{
        char first;
        int second;
        long third;
    }examp;

    那么union的分配长度就是long的长度。
    共用体很穷,舍不得给每个成员分配地方,所以按照最大需要的来分配,其他的成员就先将就用。

    结构体每个成员都会给分配空间。

    struct tagA{
        char first;
        int second;
        long third;
    }examp;

    那么分配的长度就是char+int+long。

    3、例子

    例1

    union tagAAA
    {
        struct{
            char ucFirst;
            short usSecond;
            char ucThird;
        }half;
        long lI;
    }number;

    字节对齐为1,对于union中的结构体half,长度为char+short+char=1+2+1=4;long长度也为4;按照最大长度来分配,sizeof(union tagAAA)=4。
    相应的测试代码如下:

    #include <stdio.h>
    
    #pragma pack(1)
    union tagAAA
    {
        struct{
            char ucFirst;
            short usSecond;
            char ucThird;
        }half;
        long lI;
    }number;
    
    int main(void)
    {
        printf("size of number is %d\n",sizeof(number));
    
        getchar();
        return 0;
    }

    运行结果为4.

    4字节对齐,对于half,假设char ucFirst1个字节分配地址0,short需要分配两个字节并且需要2的整数倍地址,只能是地址2和地址3(地址1就没有使用),char ucThird一个字节分配地址5,所以half一共需要5个地址,但是是四字节对齐的,要分配就给4的整数倍。我需要5个字节,所以要分配8个字节。
    对于long,需要4个字节。本着union满足最大需要分配的前提,union tagAAA分配8个字节。

    类比着住旅馆,每个房间有1张床,并且旅馆规定只能订连号的房间,并且必须订4的整数间房子,起始房间号必须是4的倍数。也就是说,你可以一间都不订,要订就得是4间、8间、12间这么订,并且房间号必须是从0、4、8······这些房间开始。
    现在来了一家三口,丈夫说我睡一张床就行,孩子说我要两张床,我住一间,另一间放玩具,并且我要住偶数号的房间,妻子说我也住一张床就行。丈夫住0号房间,孩子要住偶数房间,所以住2号,玩具放3号,1号房间没人住,也要包下来。妻子住4号房间。这样一共是五间房子,前台说我们只租4的整数倍,所以需要八间房子。类比的不是很恰当,领会意思即可。
    相应的测试代码如下:

    #include <stdio.h>
    
    union tagAAA
    {
        struct{
            char ucFirst;
            short usSecond;
            char ucThird;
        }half;
        long lI;
    }number;
    
    int main(void)
    {
        printf("size of number is %d\n",sizeof(number));
    
        getchar();
        return 0;
    }

    运行结果为8.

    例2

    struct tagBBB
    {
        char ucFirst;
        short usSecond;
        char ucThird;
        short usForth;
    }half;

    1字节对齐,char+short+char+short=1+2+1+2=6。
    测试代码:

    #include <stdio.h>
    
    #pragma pack(1)
    struct tagBBB
    {
        char ucFirst;
        short usSecond;
        char ucThird;
        short usForth;
    }half;
    
    int main(void)
    {
        printf("size of half is %d\n",sizeof(half));
    
        getchar();
        return 0;
    }
    

    4字节对齐,char ucFirst分配到地址0,short usSecond需要2的倍数地址,分配到地址2、3,char ucThird分配到地址4,usForth分配到6、7。一共需要8个字节。
    测试代码:

    #include <stdio.h>
    
    struct tagBBB
    {
        char ucFirst;
        short usSecond;
        char ucThird;
        short usForth;
    }half;
    
    int main(void)
    {
        printf("size of half is %d\n",sizeof(half));
    
        getchar();
        return 0;
    }

    例3

    struct tagCCC
    {
        struct 
        {
            char ucFirst;
            short usSecond;
            char ucThird;
        }half;
        long lI;
    };

    1字节对齐,对于half,char+short+char=1+2+1=4,long=4,所以一共需要8个字节。
    4字节对齐,对于half,char ucFirst分配地址0,short usSecond分配2的整数倍地址,分配地址2、3,ucThird分配地址4,所以half需要8个字节的地址(详细说明参见住宾馆的那个例子)。对于long,需要4个字节,所以一共需要12个字节。
    测试代码和上面类似,只不过改一下结构体就可以,这里就不给出了。

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,490
精华内容 4,196
关键字:

字节对齐