前言
问题出现于实际工作当中,最近代码里引进了一个宏offsetof(s,m),这个宏的实际作用就是用来计算结构中的某个变量在结构中的偏移量的,实际的项目是跨平台的,原来一直在windows上开发,今天发现在linux编译的日志中出现了如下的警告:
xxxx.cpp:8: 警告:对 NULL 对象非静态数据成员‘XXX::xxx’的访问无效 xxxx.cpp:8: 警告:(可能错误使用了‘offsetof’宏)
这个问题实际测试下来仅仅是个警告,没有对程序运行产生影响,但对于多数拥有强迫症的程序猿来说,这是不可忍受的,必须把这个警告搞掉。
编码测试
简单代码测试
#include <stdio.h>
#include <stdlib.h>
#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
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的时候会报警告,我就改个别的值好了…
AlbertS
认证博客专家
Python
C/C
分布式
一个手残党怀着对游戏的好奇心踏上了开发之路,旅途中磕磕绊绊踩了不少坑,触了不少雷,深知好记性不如烂笔头的道理,于是记录下学习路上的点点滴滴,携码起舞,与君共勉。Coding是件有趣的事情,快乐的看待每一天,我真的非常幸福~
转载请注明原文地址: https://ju.6miu.com/read-27458.html