免费注册 查看新帖 |

Chinaunix

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

内存对齐问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-04-26 13:42 |只看该作者 |正序浏览
在struct、class中编译器会进行内存对齐,如
  1. #include <stdio.h>
  2. typedef struct
  3. {
  4. char a;
  5. int b;
  6. int c;
  7. } A;
  8. typedef struct
  9. {
  10. char a;
  11. short b;
  12. int c;
  13. } B;
  14. int main()
  15. {
  16. printf("%d\t%d\n", sizeof(A), sizeof(B));
  17. return 0;
  18. }
复制代码
结果是:12    8
但为什么short的对齐是2而不是int的4;(对齐方式是与sizeof成正比)
为什么这样对齐效率才高?

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
19 [报告]
发表于 2010-05-04 17:05 |只看该作者
回复  star1983653
我的是64位的系统,应该能度8字节吧;
这样的话就对齐到8字节如何呢?
zxrjkl 发表于 2010-04-26 16:13


不一定。有时是1字节,有时是2字节,有时是4、8、16字节(如long double类型)。
看我上边的程序,max_allign就是用来记录结构中最大的成员。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
18 [报告]
发表于 2010-05-04 16:35 |只看该作者
本帖最后由 yulihua49 于 2010-05-04 17:07 编辑
typedef struct

{

char a;

short b;

int c;

} B;


这个short不是紧接着char a 后面的, ...
deanshuai 发表于 2010-04-26 21:01



32位linux的double是4字节对齐,64位是8字节对齐。
给你一个边界对齐的计算程序:这个程序用于分析未知结构的成员,数量类型,长度,位置(边界对齐),格式和整个结构的尺寸。


  1. #include <pack.h>

  2. #define M_ST_OFF(struct_type, member)    \
  3.         (int)((void *) &(((struct_type*) 0)->member))
  4. //这些结构用来测试各种数据的边界对齐规则,不要猜,要让编译器自己说。
  5. typedef struct {
  6.     char a;
  7.     long b;
  8. } align;
  9. typedef struct {
  10.     char a;
  11.     double b;
  12. } dalign;
  13. typedef struct {
  14.     char a;
  15.     long double b;
  16. } dfali;
  17. typedef struct {
  18.     char a;
  19.     INT64 b;
  20. } lfali;

  21. int set_offset(T_PkgType *pkg_type)
  22. {
  23. int i,k;
  24. int ali,dali,lali,ldli;
  25. int max_allign=1;

  26.     if(pkg_type->offset>-1) return cnt_type(pkg_type);
  27.     ali= M_ST_OFF(align,b) - 1;
  28.     dali=M_ST_OFF(dalign,b) - 1;
  29.     lali= M_ST_OFF(lfali,b) - 1;
  30.     ldli= M_ST_OFF(dfali,b) - 1;
  31.     k=0;
  32.     for(i=0;pkg_type[i].type>-1;i++){
  33.         pkg_type[i].offset=k;
  34.         pkg_type[i].bindtype=0;
  35.         if((pkg_type[i].type&127)!=CH_CLOB)k+=pkg_type[i].len;
  36.         else k+=sizeof(char *);
  37.         switch(pkg_type[i+1].type&127) {
  38.             case 127:
  39.             case CH_CHAR:
  40.             case CH_BYTE:
  41.             case CH_TINY:
  42.                 break;
  43.             case CH_INT64:
  44.                 k=(k+lali)&~lali;
  45.                 max_allign=(max_allign>sizeof(INT64))?max_allign:sizeof(INT64);
  46.                 break;
  47.             case CH_LDOUBLE:
  48.                 k=(k+ldli)&~ldli;
  49.                 break;
  50.             case CH_DOUBLE:
  51.                 k=(k+dali)&~dali;
  52.                 max_allign=(max_allign>sizeof(double))?max_allign:sizeof(double);
  53.                 break;
  54.             case CH_SHORT:
  55.                 k=(k+1)&~1;
  56.                 max_allign=(max_allign>sizeof(short))?max_allign:sizeof(short);
  57.                 break;
  58.             case CH_CLOB:
  59.                 k=(k+(sizeof(char *)-1)) & ~(sizeof(char *)-1);
  60.                 max_allign=(max_allign>sizeof(char *))?max_allign:sizeof(char *);
  61.                 break;
  62.             case CH_FLOAT:
  63.             case CH_INT:
  64.                 k=(k+3)&~3;
  65.                 max_allign=(max_allign>sizeof(int))?max_allign:sizeof(int);
  66.                 break;
  67.             case CH_LONG:
  68.                 max_allign=(max_allign>sizeof(long))?max_allign:sizeof(long);
  69.             default:
  70.                 k=(k+ali)&~ali;
  71.                 break;
  72.         }
  73.     }
  74. // 2009-06-22 by ylh,adjuct to struct align
  75. //  pkg_type[i].offset=(k+ali)&~ali;
  76.     if(max_allign>1) {
  77.         max_allign--;
  78.         pkg_type[i].offset=(k+max_allign)&~max_allign;
  79.     }
  80.     pkg_type[i].bindtype=0;
  81.     return i;
  82. }

  83. pack.h的部分内容:
  84. #include <sys/types.h>
  85. #include <datejul.h>

  86. #define CH_BYTE 0
  87. #define CH_CHAR 1
  88. #define CH_TINY 2
  89. #define CH_SHORT 3
  90. #define CH_INT 4
  91. #define CH_LONG 5
  92. #define CH_INT64 6
  93. #define CH_FLOAT 7
  94. #define CH_DOUBLE 8
  95. #define CH_LDOUBLE 9
  96. #define CH_CLOB 126

  97. extern const char NAN[sizeof(double)];
  98. #define DOUBLENULL (*(double *)NAN)
  99. #define FLOATNULL (*(float *)NAN)
  100. #define SHORTNULL (short)(1<<(8*sizeof(short)-1))
  101. #define INTNULL   (int)(1<<(8*sizeof(int)-1))
  102. #define LONGNULL  (1L<<(8*sizeof(long)-1))
  103. #define INT64NULL  ((INT64)1<<(8*sizeof(INT64)-1))
  104. #define TINYNULL  0X80


  105. /*****************************************************
  106. * define extend data type for net_pack()
  107. *****************************************************/
  108. #define CH_DATE     CH_CHAR|0x80
  109. #define CH_CNUM     CH_CHAR|0x100
  110. #define CH_JUL      CH_INT4|0X80
  111. #define CH_MINUTS   CH_INT4|0x100
  112. #define CH_TIME     CH_INT64|0x80
  113. #define CH_USEC     CH_INT64|0x200
  114. /* used by varchar2 as date(year to day),default format is "YYYYMMDD" */
  115. #define CH_CJUL     CH_INT4|0x200
  116. #define CH_CMINUTS  CH_INT4|0x400
  117. /* used by varchar2 as date(year to sec),default format is "YYYYMMDDHH24MISS" */
  118. #define CH_CTIME    CH_INT64|0x100
  119. //这个就是所谓的“模板”了,它使我们能够"看"到未知结构的内容。
  120. typedef struct {
  121.         INT4 type;
  122.         INT4 len; // in byte
  123.         char *name;
  124.         const char *format;
  125.         INT4 offset;
  126.         int bindtype; //default=0
  127. } T_PkgType;
  128. // for bindtype
  129. #define RETURNING 1     //this column only for returnning
  130. #define NOINS     2 //this column don't insert or update
  131. #define NOSELECT  4     //this column don't select only used by bind



复制代码
以上就是 结构-关系映像(SRM,Struct Relational mapping) 最核心的内容。SRM完成把结构的内容与字符串互相映像(结构变字符串,也叫序列化,字符串变结构,也叫反序列化;
结构内容进入数据库表,数据库表的内容进入结构;JSON与结构的互相映射等等。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
17 [报告]
发表于 2010-05-04 16:33 |只看该作者
在struct、class中编译器会进行内存对齐,如结果是:12    8
但为什么short的对齐是2而不是int的4;(对齐 ...
zxrjkl 发表于 2010-04-26 13:42



  sizeof(struct)与边界对齐并不完全等同。
sizeof以结构中最大尺寸的成员(不包括结构)的尺寸对齐。

论坛徽章:
0
16 [报告]
发表于 2010-05-01 11:05 |只看该作者
回复 15# zxrjkl


    如果一个 2 字节区域不作对齐,是可以跨越两个 8 字节对齐的单元的。

论坛徽章:
0
15 [报告]
发表于 2010-04-26 22:02 |只看该作者
回复 13# 变异老鼠
那我就算不对齐也可以一次读入

论坛徽章:
0
14 [报告]
发表于 2010-04-26 21:01 |只看该作者
typedef struct

{

char a;

short b;

int c;

} B;


这个short不是紧接着char a 后面的,应该是空一个字节。我之前在linux测试过double对齐问题,发现linux下,doubule也是4字节对齐。应该是编译做了优化。

论坛徽章:
0
13 [报告]
发表于 2010-04-26 20:41 |只看该作者
回复 11# zxrjkl


    一块 2 字节的内存空间,只要它是 2 字节对齐的,就必然在某个 8 字节对齐的 8 字节内存空间内,而这个 8 字节空间是可以一次读入的。所以盲目扩大对齐要求,不但不会加速,反而浪费空间。

论坛徽章:
0
12 [报告]
发表于 2010-04-26 16:47 |只看该作者
你编译出的程序是32位的,即使CPU是64位的也没有用。纯属浪费!

论坛徽章:
0
11 [报告]
发表于 2010-04-26 16:13 |只看该作者
回复 10# star1983653
我的是64位的系统,应该能度8字节吧;
这样的话就对齐到8字节如何呢?
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP