关于使用sizeof 进行地址偏移,导致问题

[复制链接]
937|9
手机看帖
扫描二维码
随时随地手机跟帖
suxilong|  楼主 | 2018-10-24 10:22 | 显示全部楼层 |阅读模式
本帖最后由 suxilong 于 2018-10-24 11:09 编辑

如下所示,定义了两个结构体,
然后使用宏 定义了一个地址, 地址通过 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)<I>         g_test:0xbfc0bfb5
(181024_10:10:55.315)<I>         u8_g2:0xbfc0bfb9
(181024_10:10:55.315)<I>         g2_g2:0xbfc0bfb9
(181024_10:10:55.315)<I>         u8_g3:0xbfc0bfbb
(181024_10:10:55.315)<I>         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)<I>g_test:0xbfc0bfb5
(181024_10:39:49.283)<I>u8_g2:0xbfc0bfb7
(181024_10:39:49.283)<I>g2_g2:0xbfc0bfb7
(181024_10:39:49.283)<I>u8_g3:0xbfc0bfb8
(181024_10:39:49.283)<I>g3_g3:0xbfc0bfb8
(181024_10:39:49.283)<I>sizeof g2:0x00000002
(181024_10:39:49.283)<I>sizeof g3:0x00000003


修改#define g_test                        (g_test_3_t  *)(0xbfc0bfb5)
打印:
(181024_11:07:44.918)<I>g_test:0xbfc0bfb5
(181024_11:07:44.918)<I>u8_g2:0xbfc0bfbb
(181024_11:07:44.918)<I>g2_g2:0xbfc0bfbb
(181024_11:07:44.918)<I>u8_g3:0xbfc0bfbe
(181024_11:07:44.918)<I>g3_g3:0xbfc0bfbe
(181024_11:07:44.918) sizeofg2:0x00000002
(181024_11:07:44.918) sizeof g3:0x00000003
所以问题应该是理解不透彻,


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


相关帖子

mohanwei| | 2018-10-24 10:30 | 显示全部楼层
除了8位机,其它都不是按1字节对齐的
想要强制按1字节对齐,在结构体定义前加一行:
#pragma pack(1) //1字节对齐。在和外部交换参数结构体时用到

使用特权

评论回复
评论
suxilong 2018-10-24 10:51 回复TA
这是一个32bit 的cpu ,你的意思是 字节对齐导致的? 可以怎么算也不是翻倍啊? 
ayb_ice| | 2018-10-24 14:47 | 显示全部楼层
为了对齐,中间可能有间隙
把地址0强制转换为结构体,再将各成员的地址强制转换为偏移即可

使用特权

评论回复
suxilong|  楼主 | 2018-10-25 14:34 | 显示全部楼层
ayb_ice 发表于 2018-10-24 14:47
为了对齐,中间可能有间隙
把地址0强制转换为结构体,再将各成员的地址强制转换为偏移即可 ...

因为 编译器 对#pragma pack(1) 兼容 不好!!!

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

使用特权

评论回复
ayb_ice| | 2018-10-25 17:35 | 显示全部楼层
suxilong 发表于 2018-10-25 14:34
因为 编译器 对#pragma pack(1) 兼容 不好!!!

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

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

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

使用特权

评论回复
linqing171| | 2018-10-25 17:42 | 显示全部楼层
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都是必须的。



使用特权

评论回复
john_lee| | 2018-10-26 00:39 | 显示全部楼层
指针加整数,偏移量并不是简单的增加了整数个字节,而是增加了(指针的类型大小×整数)个字节。
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)] 是相同的。

使用特权

评论回复
千岁寒| | 2018-11-2 15:42 | 显示全部楼层
建议试试  pack 属性配置

使用特权

评论回复
jackyhuang1988| | 2018-11-3 09:02 | 显示全部楼层
指针+1,偏移量是指针指向的数据类型的大小

#define u8_g2    ((uint8 *)(g_test+sizeof(g_test_2_t)))             这样偏移了n个结构体

#define u8_g2        ((uint8 *)(g_test) + sizeof(g_test_2_t))       这样才偏移一个结构体
或者  #define u8_g2        ((uint8 *)(g_test) + sizeof(g_test))

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

55

主题

339

帖子

4

粉丝