ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

八字节对齐

2020-07-05 18:34:35  阅读:482  来源: 互联网

标签:字节 mem stView 八字 offset 存储单元 对齐


  • 字节对齐意义

  在进行c/c++开发时,特别是要求跨平台或者网络通信的时候,都会要求进行字节对齐,那为什么需要对齐,如果不对齐会有什么问题呢。

  (1) 存储方式:

    现代计算机处理器对存储的读取都是按照特定大小字节去读写(称其为一个存储单元),比如一个变量char,它的长度为1,但是在存储器中它占用的空间是一个存储单               元。当变量字节长度小于等于一个存储单元时,都将分配一个存储单元,且存储空间永远是存储单元的整数倍。

  (2)读写效率:

    CPU访问内存都是一次访问一个存储单元,比如32位linux系统一个存储单元为4字节,当需要读取一个int数据时,只需要读取一次,如果存储单元为1字节,则需要读取4       次,通过移位等运算计算出一个int值,同样的读取一个int值,其访问内存及运算的次数远远低于一次读取一个字节。

  (3)跨平台问题:

     各个硬件平台对存储空间的处理不尽相同,比如一些CPU访问特定的变量必须从特定的地址进行读取,嵌入式ARM架构和我们平时使用的x86架构以及不同的操作系统比如       32位操作系统和64位操作系统对存储的管理和存储单元的读写都不尽相同,如果我们的代码需要在不同的平台上运行该怎么办,我们不能每种架构和每种系统都开发一套程序                   吧。此时我们需要定义一种通用的字节对齐方式,不管什么架构与系统都能能数据进行完整正确的读写。

  (4)网络通信问题:

    在进行网络通信的时候,如果是相同的平台间进行,则无需关心字节问题,但是跨平台的通信,由于不同架构和操作系统对存储的管理不同,如果不采用发送及接收方都满      足的字节对齐方式,将导致数据的错乱甚至是程序的崩溃。

  (5)字节对齐解决的问题:

     上面所说的问题,其实都是CPU读写是以存储单元进行的,但是我们实际运用的类型的数据大小并非和存储单元大小相同,所以存储单元存在字节填充的问题,我们的构      建的结构体等数据结构,不存在字节填充,那么上面的问题都不将存在,所以说,字节对齐是一种契约,主要解决字节填充问题。

  (6)为什么选择8字节对齐:

    就目前而言,64位操作系统默认是8字节对齐的,8字节对齐能满足各种计算架构和系统。

  • 结构体内存布局

    比如有如下结构体:

    

    32位操作系统输出:offset[a: 0, d:  4, c: 12] size: 16

     64位操作系统输出:offset[a: 0, d:  8, c: 16] size: 24

     为何差别会这么大,因为32为操作系统是4字节对齐(一个存储单位为4字节),64位操作系统位8字节对齐(一个存储单元为8字节)

     如上结构体内存布局如下图所示:

    

 

    内存布局规则(32位系统4字节为存储单元为例):

    (1)如果当前的存储单元空间能不小于当前变量的大小,则存储到该存储空间,否则存储到另一个存储空间。

    (2)如果变量大小查过存储单元,则分配多个存储单元进行存储。

    (3)向后看齐,在一个存储单元中存在不同类型,则前面的成员向后补齐,比如存在相邻两个成员char和short,在存储short成员的时候相对char偏移两个字节。

 

  • 8字节对齐规则

    字节对齐主要是消除系统的字节填充,规则如下:

    (1)结构体内不存在字节填充。

    (2)结构体大小为8字节的整数倍。

     在构建结构体时,注意以下事项:

    (1)相同的类型尽量放在一块

    (2)小字节类型尽量放在大字节类型之前

    (3)避免有填充字节存在

    (4)结构体大小为8的整数倍

  • 8字节检测与对齐算法实现

    有时候我们需要一些工具来检测8字节是否对齐或者生成一个对齐的结构体。

    因为一般工具都选择python实现,以下为python实现的8字节检测与实现的代码(只列出检测与对齐部分,实际运用中需要进行头文件解析,提取结构体信息。枚举长度同int,结构体长度为  8,联合体当结构体处理,检测每一个结构体,如果都是8字节对齐,那该结构体即为8字节对齐)

 1 # !/usr/bin/python
 2 # coding=UTF-8
 3 
 4 BITOFFSET = lambda x, align: (x+(align-1)) & ~(align-1)
 5 
 6 
 7 class STView(object):
 8 
 9     def __init__(self):
10         self.name = None    # 结构体名
11         self.members = []   # 结构体成员,STMemberView对象
12 
13 
14 class STMemberView(object):
15 
16     def __init__(self, name=None, type_=None, size=None, number=1):
17         self.name = name    # 结构体成员名
18         self.type = type_    # 结构体成员类型
19         self.size = size    # 结构体成员大小
20         self.number = number     # 结构体成员数组大小
21 
22 
23 def check8bit(stView=STView()):
24     """
25     8字节检测
26     :param stView:
27     :return:
28     """
29     offset = 0
30     for mem in stView.members:
31         offset2 = BITOFFSET(offset, int(mem.size))
32         if offset2 != offset:
33             print "structural {0} is not 8 bit aligned with {1}. need {2} bit before {1}".\
34                 format(stView.name, mem.name, offset2-offset)
35             return False
36         else:
37             offset += mem.number * int(mem.size)
38     offset2 = BITOFFSET(offset, 8)
39     if offset2 != offset:
40         print "structural {0} is not 8 bit aligned with end. need {1} bit before end". \
41             format(stView.name, offset2 - offset)
42         return False
43     return True
44 
45 
46 def align8bit(stView=STView()):
47     """
48     8字节自动填充
49     :param stView:
50     :return:
51     """
52     flag = index = offset = 0
53     while index < len(stView.members):
54         offset2 = BITOFFSET(offset, int(stView.members[index].size))
55         if offset2 != offset:
56             align_mem = STMemberView("filled_{0}".format(flag), "char", 1, offset2-offset)
57             stView.members.insert(index, align_mem)
58             flag += 1
59         else:
60             offset += stView.members[index].number * int(stView.members[index].size)
61             index += 1
62     offset2 = BITOFFSET(offset, 8)
63     if offset2 != offset:
64         align_mem = STMemberView("filled_{0}".format(flag), "char", 1, offset2 - offset)
65         stView.members.insert(index + 1, align_mem)
66     return True
67 
68 
69 if __name__ == "__main__":
70     st = STView()
71     """
72     例如结构体:
73     tt
74     {
75         char m1;
76         //此处差3字节
77         int m2;
78         float m3;
79         //末尾不对齐
80     }
81     """
82 
83     st.name = "tt"
84 
85     st.members.append(STMemberView('m1', "char", 1))
86     st.members.append(STMemberView('m2', "int", 4))
87     st.members.append(STMemberView('m3', "float", 4))
88 
89     check8bit(st)
90 
91     align8bit(st)
92     for mem in st.members:
93         print mem.name, mem.type, mem.size, mem.number

 执行结构如下:

 

 

    

标签:字节,mem,stView,八字,offset,存储单元,对齐
来源: https://www.cnblogs.com/lwp-boy/p/13191838.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有