指针加法中的隐形偏差:一次不该有的偏移踩坑

在最近的开发中,有这样的一个需求,给一个结构体,我需要传出这个结构体的个别成员的地址,offsetof这个宏函数可以很好的解决这个业务需求,但是我还是踩坑了。下面看看我的踩坑记录。

我们知道一个(TInfoRom*)infoRom类型的结构体指针,他指向当前结构体变量的首地址。我们可以通过offsetof算出nRerpMode在TInfoRom偏移的字节数再加上当前结构体变量的首地址infoRom。就可以得到我们想要的addressOfRerpMode了。下面我给出了我踩坑之前的代码和修正后的代码。

// 结果理想
addressOfRerpMode = (void*)(     offsetof(TInfoRom, nRerpMode)  + (char*)infoRom);
// 结果不理想
addressOfRerpMode = (void*)((u64)offsetof(TInfoRom, nRerpMode)  +        infoRom);
// 不理想的结果与下面等价
addressOfRerpMode = (void*)((u64)offsetof(TInfoRom, nRerpMode)  * sizeof(infoRom));

infoRom是TInfoRom的指针类型,offsetof(TInfoRom, nRerpMode)的返回值是一个无符号的整型(具体的位数根据操作系统的位数自动适应)。踩坑的原因是我用一个整型去加一个TInfoRom的指针类型,假如offsetof(TInfoRom, nRerpMode)的值为2,那我其实加了2*sizeof(infoRom)的地址。所以需要通过强制转换为(char*),这样再加的话加的就是2*sizeof(char)的地址,就是我们想要的结果了。

这次事故让我深刻认识到,指针的每一步操作都需要足够的严谨性,尤其是在跨类型操作时。指针算术中隐形的偏差,常常在不经意间引入难以察觉的错误。

我们要始终对数据类型的大小、指针的运算方式以及系统对齐要求有深刻的理解。只有这样,才能在复杂项目中编写出稳定且高效的代码。

希望我的这次经历能为你提供一些启示或帮助。如果你也有类似的踩坑经历,欢迎在评论区交流!

posted @ 2024-11-13 15:53  小兜兜me  阅读(11)  评论(0编辑  收藏  举报