user-0 提问: 指向指针的指针 对齐问题

回复:
user: user-1
content: 首先你要理解pack（1）是什么意思，他是程序的，内存是一字节对齐，这样你的指针很有可能不在4字节的边界这样就会出错（x86没有这个问题），在一个这个4字节对齐是芯片要求的arm体系结构。   难道我解引一个指针即使使用了pack(1)下还必须4字节对齐。  你这么问感觉不了解pack(1)是什么意思，就因为你pack(1)啦才让程序1字节对齐的啊

user: user-2
content: void  test(AA_T *p)  {      printf("\n 0x%x", p->pBB ->b1);  }    把pAA的地址扔进去，再试，看咋样

user: user-0
content: 有哪位可以解释一下，为什么将二级指针作为函数形参就出错了。我试了一下  如果不做函数形参执行是不会出错的 我都快疯了。

user: user-0
content: 谢谢各位 。我把问题重新贴一下吧。可能大家没看明白。  在使用pack(1)的情况下，双重指针作为子函数参数传递，子函数内部解引指针出现错误。原因是没有对齐在4字节边界上。 但是不知道为什么使用了pack(1)还会出现这样的错误。请各位看客分析下。 因为的数据要发送到非常窄的链路上，所以我必须pack(1)。但是又出现这样的错误，很难受。  简要的代码结构描述：（下面的代码经过试验，能够复现问题） 平台：ARM9 系统：vxworks6.6  //头文件  #pragma pack(1) typedef struct {      char a;     int  c;     BB_T *pBB; }AA_T;  typedef struct {     char a;     int  c; }BB_T; #pragma pack(0)   //C文件  /* 定义了两个变量*/ AA_T g_struAA;   BB_T g_struBB;   void  test(BB_T **ppstruBB) {     BB_T *pstruBB = NULL;      pstruBB = *ppstruBB;     /* 解引一级指针 */     printf("\n 0x%x ",pstruBB ->c);  /* 输出值 正确下应该是 0x12345678 */}  void  testmain(){ /* 初始化 */     g_struBB.a = 1;    g_struBB.c = 0x12345678;  /* 初始化 */    g_struAA.a = 1;   g_struAA.c = 2;     g_struAA.pBB = &g_struBB;      test(&g_struAA.pBB); }   // 运行结果  直接奔溃。执行到test的解引那个语句的时候出错。 但是去掉pack(1)  和pack(0)就好了。 为什么呢？ 难道我解引一个指针即使使用了pack(1)下还必须4字节对齐。困扰好久，求各位看官多多赐教。

user: user-3
content: 引用 7 楼 nice_cxf 的回复:有些linux系统，指针必须指向4字节的整数倍（32位系统），因此当你按照1字节对齐时，指针指向的位置不能保证4字节的整数倍，所以就出错了 纠正：有些CPU（比如ARM），……

user: user-4
content: 有些linux系统，指针必须指向4字节的整数倍（32位系统），因此当你按照1字节对齐时，指针指向的位置不能保证4字节的整数倍，所以就出错了

user: user-3
content: #include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD  { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1  { int a; char b[13]; double c;}; #pragma pack(2) struct A2  { int a; char b[13]; double c;}; #pragma pack(4) struct A4  { int a; char b[13]; double c;}; #pragma pack(8) struct A8  { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() {     printf("AD.a %d\n",field_offset(AD,a));     printf("AD.b %d\n",field_offset(AD,b));     printf("AD.c %d\n",field_offset(AD,c));     printf("\n");     printf("A1.a %d\n",field_offset(A1,a));     printf("A1.b %d\n",field_offset(A1,b));     printf("A1.c %d\n",field_offset(A1,c));     printf("\n");     printf("A2.a %d\n",field_offset(A2,a));     printf("A2.b %d\n",field_offset(A2,b));     printf("A2.c %d\n",field_offset(A2,c));     printf("\n");     printf("A4.a %d\n",field_offset(A4,a));     printf("A4.b %d\n",field_offset(A4,b));     printf("A4.c %d\n",field_offset(A4,c));     printf("\n");     printf("A8.a %d\n",field_offset(A8,a));     printf("A8.b %d\n",field_offset(A8,b));     printf("A8.c %d\n",field_offset(A8,c));     printf("\n");     printf("A16.a %d\n",field_offset(A16,a));     printf("A16.b %d\n",field_offset(A16,b));     printf("A16.c %d\n",field_offset(A16,c));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 // //A1.a 0 //A1.b 4 //A1.c 17 // //A2.a 0 //A2.b 4 //A2.c 18 // //A4.a 0 //A4.b 4 //A4.c 20 // //A8.a 0 //A8.b 4 //A8.c 24 // //A16.a 0 //A16.b 4 //A16.c 24 // //

user: user-0
content: 因为我必须要用1字节对齐。所以我没法改。 可以分析下还有好的方法么？

user: user-5
content: typedef struct {     int a1;     short a2;    /* 一堆变量 */     BB_T *pBB; }AA_T; 你尝试这把这两个结构体，不论是4字节对齐还是1字节对齐，都先让其定义上做到4字节对齐（调换一下结构体成员的位置，把占用内存字节数最大的成员放在前面）。

user: user-0
content: 刚才上面的回复 &&g_struBB 多打了个 &。

user: user-0
content: 我继续查了下 发现出错的地方是在执行语句 ptestbb  = *ppTest; 的时候出错的。  *ppTest得到的地址已经不正确了，已经不是&&g_struBB 我真不明白为什么不正确。 所以导致接下来执行 printf("\n 0x%x", ptestbb ->b1); 指针飞了。 真搞不懂。 如果不强制1字节对齐就可以。强制1字节对齐就不行。但是我的代码所实现的功能又必须强制1字节对齐。

user: user-6
content: 应该是不影响嘛，我看不出来有什么问题，或许问题不是出在此处？