可能错误使用了‘offsetof’宏

来源:互联网 发布:倪妮周冬雨知乎 编辑:程序博客网 时间:2024/05/05 19:11

前言

问题出现于实际工作当中,最近代码里引进了一个宏offsetof(s,m),这个宏的实际作用就是用来计算结构中的某个变量在结构中的偏移量的,实际的项目是跨平台的,原来一直在windows上开发,今天发现在linux编译的日志中出现了如下的警告:

xxxx.cpp:8: 警告:对 NULL 对象非静态数据成员‘XXX::xxx’的访问无效
xxxx.cpp:8: 警告:(可能错误使用了‘offsetof’宏)

这个问题实际测试下来仅仅是个警告,没有对程序运行产生影响,但对于多数拥有强迫症的程序猿来说,这是不可忍受的,必须把这个警告搞掉。

编码测试

  • 简单代码测试
#include <stdio.h>#include <stdlib.h>/* Define offsetof macro */#ifdef __cplusplus#ifdef  _WIN64#define offsetof(s,m)   (size_t)( (ptrdiff_t)&reinterpret_cast<const volatile char&>((((s *)0)->m)) )#else#define offsetof(s,m)   (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))#endif#else#ifdef  _WIN64#define offsetof(s,m)   (size_t)( (ptrdiff_t)&(((s *)0)->m) )#else#define offsetof(s,m)   (size_t)&(((s *)0)->m)#endif#endif  /* __cplusplus */struct STest{        int nValue1;        int nValue2;        int nValue3;        static int nCount;        char cValue4;        char cValue5;        STest()        {                nValue1 = 1;                nValue2 = 3;        }};int main(){        STest test;        test.nValue1 = 101;        test.nValue2 = 110;        test.nValue3 = 119;        int n1 = offsetof(STest, nValue1);        int n2 = offsetof(STest, nValue2);        int n3 = offsetof(STest, nValue3);        int n4 = offsetof(STest, cValue4);        int n5 = offsetof(STest, cValue5);        printf("n1 = %d\n", n1);        printf("n2 = %d\n", n2);        printf("n3 = %d\n", n3);        printf("n4 = %d\n", n4);        return 0;}

其中关于offsetof的宏定义我是从stddef.h中复制出来的,这个文件是vs安装时自带的目录中发现的。

  • 测试结果


    有警告的编译结果

  • 分析

    这个警告中的NULL比较扎眼,考虑把它搞掉们是不是只有NULL才会报警告呢,参考了其他平台和工具的offsetof宏定义,决定把当前环境中的offsetof宏定义改一下:

    #define offsetof(s,m)   (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))

    改成

    #define offsetof(s,m)   (size_t)(&reinterpret_cast<const volatile char&>((((s*)0x11)->m)) - 0x11)

    改完后然后重新编译

  • 第二次编译结果


     去掉警告的编译结果

总结

看来这g++编译器对NULL很敏感嘛!既然是0的时候会报警告,我就改个别的值好了…

1 0