请教一个老问题:C语言结构体的内存分配?困惑!!!

时间:2021-11-21 02:29:50
struct test{
  char a;
  short b;
  int c;
  int d;
};
这个结构体的sizeof(test)=12,可以理解,内存对齐,char(1),short(2),int(4),对齐int为12。
大家再看下面两个结构体:
struct test1{
  char a;
  char e;
  short b;
  int c;
  int d;
};
struct test2{
  char a;
  short b;
  char e;
  int c;
  int d;
};
这时sizeof(test1)=12,而sizeof(test2)=16;
这就叫人困惑了,结构体test1中内存对齐两个char和short正好是4;而结构体test2中也是一样,按理说应该也是12,为什么就是16了?编译器到底怎么给结构体分配内存的?请高手指点!!

6 个解决方案

#1


单字节变量以单字节对齐,双字节变量以双字节对齐,四字节和以上长度变量以四字节对齐。
我一般就是这样理解的。

#2


a b   4
e     4
c     4
d     4

#3


这个由变量自身对齐值和指定对齐值中小的那个来决定。
a.数据类型自身的对齐值:
   对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。
b.指定对齐值: #pragma pack (value)时的指定对齐值value。

1) 不是所有的系统都不支持字节对齐.
2) 编译器怎样设置字节对齐,不是所有平台都支持,X86是支持的,ARM编译器会出warnings.
 #pragma pack(n) /* 其中n表示按n 字节对齐 */
 #pragma pack()  /* 取消指定对齐,恢复初始值 */
 例如:
    struct abc{
        char c1, c2, c3;
        short ui;
        int i;
    }
    pack(1) sizeof(struct abc)=>9
    pack(2) sizeof(struct abc)=>10
    pack(4) sizeof(struct abc)=>12
3) 就算系统支持字节对齐访问,但是也不一定访问的数据就是正确的,这个看起来比较恐怖,看样子好像都没有问题,
真正到了Target Board上的时候就是不正确,基本上可能就是这个引起的。
  例如:
      int i=0x12345678;
      char *p=NULL;
      short *p1=NULL;
      
      p = &i;
      p1 = (short *)(p+1);
      *p1 = 0x0000;
      
      printf("p:%p\n", p);
      printf("p1:%p\n", p1);
      printf("i:%x\n", i);
  #在Intel X86 平台上输出为:
      p: 0xbfe70ce8
      p1: 0xbfe70ce9
      i: 120078
  #而在 ARM上面却是:
      p: 0x9220ff20
      p1: 0x9220ff21
      i: 12340000
  从上面的结果中可以很明显的看出,ARM平台虽然支持字节对齐操作,但是到正确访问的时候却
  是错误的。
4) 参考文章:
   a) http://www.yuanma.org/data/2006/0723/article_1213.htm
   b) http://www.devx.com/tips/Tip/13265
   c) http://www.chinaitpower.com/2005September/2005-09-13/206312.html
   d) http://www.chinaitpower.com/A/2003-01-03/45873.html

#4


test1:---- ---- ---- ----
      aebb cccc dddd         (12)
test2:---- ---- ---- ----
      a bb e    cccc dddd    (16)

空格表示不存储变量这样清楚点吗?

#5


多谢各位大虾指点!
但你们说的我都知道,还是没有回答我的问题为什么会是这样?

#6


内存访问问题,大多数编译器默认为内存单元是4字节,因为这个时候内存访问效率最好,
  所以一般都是以4字节对齐的。(不知道错了没有。。:))

#1


单字节变量以单字节对齐,双字节变量以双字节对齐,四字节和以上长度变量以四字节对齐。
我一般就是这样理解的。

#2


a b   4
e     4
c     4
d     4

#3


这个由变量自身对齐值和指定对齐值中小的那个来决定。
a.数据类型自身的对齐值:
   对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。
b.指定对齐值: #pragma pack (value)时的指定对齐值value。

1) 不是所有的系统都不支持字节对齐.
2) 编译器怎样设置字节对齐,不是所有平台都支持,X86是支持的,ARM编译器会出warnings.
 #pragma pack(n) /* 其中n表示按n 字节对齐 */
 #pragma pack()  /* 取消指定对齐,恢复初始值 */
 例如:
    struct abc{
        char c1, c2, c3;
        short ui;
        int i;
    }
    pack(1) sizeof(struct abc)=>9
    pack(2) sizeof(struct abc)=>10
    pack(4) sizeof(struct abc)=>12
3) 就算系统支持字节对齐访问,但是也不一定访问的数据就是正确的,这个看起来比较恐怖,看样子好像都没有问题,
真正到了Target Board上的时候就是不正确,基本上可能就是这个引起的。
  例如:
      int i=0x12345678;
      char *p=NULL;
      short *p1=NULL;
      
      p = &i;
      p1 = (short *)(p+1);
      *p1 = 0x0000;
      
      printf("p:%p\n", p);
      printf("p1:%p\n", p1);
      printf("i:%x\n", i);
  #在Intel X86 平台上输出为:
      p: 0xbfe70ce8
      p1: 0xbfe70ce9
      i: 120078
  #而在 ARM上面却是:
      p: 0x9220ff20
      p1: 0x9220ff21
      i: 12340000
  从上面的结果中可以很明显的看出,ARM平台虽然支持字节对齐操作,但是到正确访问的时候却
  是错误的。
4) 参考文章:
   a) http://www.yuanma.org/data/2006/0723/article_1213.htm
   b) http://www.devx.com/tips/Tip/13265
   c) http://www.chinaitpower.com/2005September/2005-09-13/206312.html
   d) http://www.chinaitpower.com/A/2003-01-03/45873.html

#4


test1:---- ---- ---- ----
      aebb cccc dddd         (12)
test2:---- ---- ---- ----
      a bb e    cccc dddd    (16)

空格表示不存储变量这样清楚点吗?

#5


多谢各位大虾指点!
但你们说的我都知道,还是没有回答我的问题为什么会是这样?

#6


内存访问问题,大多数编译器默认为内存单元是4字节,因为这个时候内存访问效率最好,
  所以一般都是以4字节对齐的。(不知道错了没有。。:))