单片机/MCU论坛
直播中

贾飞世

7年用户 1821经验值
私信 关注
[问答]

使用sizeof 进行地址偏移出现问题

下所示,定义了两个结构体,
然后使用宏 定义了一个地址, 地址通过 sizeof 结构体 进行地址偏移,

结果通过打印 这些地址,   发现偏移的地址 不是结构体的size。

请问为什么

typedef struct
{
     uint8 a;
     uint8 b;
} g_test_2_t;

typedef struct
{
     uint8 d;
     uint8 e;
     uint8 f;
} g_test_3_t;

#define g_test                        (g_test_2_t *)(0xbfc0bfb5)

#define u8_g2        ((uint8 *)(g_test+sizeof(g_test_2_t)))
#define g2_g2        ((g_test_2_t *)(g_test+sizeof(g_test_2_t)))

#define u8_g3        ((uint8  *)(g_test+sizeof(g_test_3_t)))
#define g3_g3        ((g_test_3_t *)(g_test+sizeof(g_test_3_t)))

使用sizeof进行地址偏移后,出现的问题:

(181024_10:10:55.315)         g_test:0xbfc0bfb5
(181024_10:10:55.315)         u8_g2:0xbfc0bfb9
(181024_10:10:55.315)         g2_g2:0xbfc0bfb9
(181024_10:10:55.315)         u8_g3:0xbfc0bfbb
(181024_10:10:55.315)         g3_g3:0xbfc0bfbb
(181024_10:10:55.315)                sizeof g_test_2_t:0x00000002
(181024_10:10:55.315)                sizeof g_test_3_t:0x00000003

如打印所示,
u8_g2 按道理偏移sizeof(g_test_2_t) 应该只是偏移2byte 结果,显示偏移了4byte 。
u8_g3 按道理偏移sizeof(g_test_3_t) 应该只是偏移3byte 结果,显示偏移了6byte 。
这到底是为什么呢?



后面我又做了 两个测试
修改#define g_test                        (uint8  *)(0xbfc0bfb5)
打印:

(181024_10:39:49.279)g_test:0xbfc0bfb5
(181024_10:39:49.283)u8_g2:0xbfc0bfb7
(181024_10:39:49.283)g2_g2:0xbfc0bfb7
(181024_10:39:49.283)u8_g3:0xbfc0bfb8
(181024_10:39:49.283)g3_g3:0xbfc0bfb8
(181024_10:39:49.283)sizeof g2:0x00000002
(181024_10:39:49.283)sizeof g3:0x00000003


修改#define g_test                        (g_test_3_t  *)(0xbfc0bfb5)
打印:

(181024_11:07:44.918)g_test:0xbfc0bfb5
(181024_11:07:44.918)u8_g2:0xbfc0bfbb
(181024_11:07:44.918)g2_g2:0xbfc0bfbb
(181024_11:07:44.918)u8_g3:0xbfc0bfbe
(181024_11:07:44.918)g3_g3:0xbfc0bfbe
(181024_11:07:44.918) sizeofg2:0x00000002
(181024_11:07:44.918) sizeof g3:0x00000003
所以问题应该是理解不透彻,



sizeof 的运算在这里是对的,它在这里只决定了偏移单位的个数。
但偏移的大小即关系到偏移单位的个数也同样关系到偏移的单位 的大小( g_test 的大小),
偏移大小 = 偏移单位个数 X 偏移单位大小

回帖(9)

王银喜

2018-10-26 09:44:27
除了8位机,其它都不是按1字节对齐的
想要强制按1字节对齐,在结构体定义前加一行:
#pragma pack(1) //1字节对齐。在和外部交换参数结构体时用到
举报

贾飞世

2018-10-26 09:44:38
这是一个32bit 的cpu ,你的意思是 字节对齐导致的? 可以怎么算也不是翻倍啊?  
举报

王强

2018-10-26 09:44:51
为了对齐,中间可能有间隙
把地址0强制转换为结构体,再将各成员的地址强制转换为偏移即可
举报

贾飞世

2018-10-26 09:45:10
因为 编译器 对#pragma pack(1) 兼容 不好

请问你 说的方法 是 如何实现? 没看懂
举报

王强

2018-10-26 09:45:25

typedef struct{
         char cVar1;
         int iVar2;
}Test_Typedef;

#define OFFSET_STRUCT(st, mem)        ((int)(&((Test_Typedef*)0)->mem))
举报

刘敏

2018-10-26 09:45:34
typedef struct
{
     g_test_2_t var1;
     unsigned char rev[1];
     g_test_3_t var2;
} struct_var ;
#define g_test                        (struct_var *)(0xbfc0bfb5)

g_test->var1.a 这样来使用才能保证var1和var2是挨着的,你那样怎么保证两个变量是挨着的?
不过无论如何pack都是必须的。
举报

王杰

2018-10-26 09:45:55
指针加整数,偏移量并不是简单的增加了整数个字节,而是增加了(指针的类型大小×整数)个字节。
g_test是个指针,类型大小为2,加上 sizeof(g_test_2_t),值为2,偏移量增加了 2×2 = 4 字节。
g_test + sizeof(g_test_2_t) 在语义上与 &g_test[sizeof(g_test_2_t)] 是相同的。
举报

NORMALVISION

2018-10-26 10:34:02
我是来学习的~~~~~~~~~
举报

xxxxxxEVER

2018-10-26 11:53:54
指针偏移量 = 指针指向数据类型大小 * 偏移个数
(g_test_2_t *)指针指向数据类型为结构体g_test_2_t,结构体数据类型大小为2
偏移个数为sizeof(g_test_2_t)为2,所以指针偏移量为2*2
偏移个数为sizeof(g_test_3_t)为3,所以指针偏移量为2*3

(uint8  *)指针指向数据类型为unsigned char,数据类型大小为1
偏移个数为sizeof(g_test_2_t)为2,所以指针偏移量为1*2
偏移个数为sizeof(g_test_3_t)为3,所以指针偏移量为1*3

(g_test_3_t*)指针指向数据类型为结构体g_test_3_t,结构体数据类型大小为3
偏移个数为sizeof(g_test_2_t)为2,所以指针偏移量为3*2
偏移个数为sizeof(g_test_3_t)为3,所以指针偏移量为3*3

举报

更多回帖

×
20
完善资料,
赚取积分