当前位置: 首页 > news >正文

可能错误使用了‘offsetof’宏

前言

问题出现于实际工作当中,最近代码里引进了一个宏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的时候会报警告,我就改个别的值好了…

相关文章:

  • 警告:对 NULL 对象非静态数据成员‘XXX::xxx’的访问无效
  • git tag常用操作
  • error: SEH exception with code 0xc0000005 thrown in the test
  • new对象数组是否会调用对象的构造函数
  • const究竟限制了谁的改变
  • CSDN 论坛板块升级规则
  • poj解题报告——序
  • UE4编辑器修改界面显示语言
  • poj解题报告——poj 2028 When Can We Meet?
  • poj解题报告——poj 1493 Machined Surfaces
  • poj解题报告——poj 2365 Rope
  • poj解题报告——poj 2575 Jolly Jumpers
  • poj解题报告——poj 3536 Beer Refrigerator
  • poj解题报告——poj 1528 Perfection
  • SVN:Fully recursive、Working copy和Immediate children...区别
  • Asm.js的简单介绍
  • js ES6 求数组的交集,并集,还有差集
  • js学习笔记
  • Laravel 菜鸟晋级之路
  • Lsb图片隐写
  • PHP变量
  • vue-cli在webpack的配置文件探究
  • Vue--数据传输
  • 诡异!React stopPropagation失灵
  • 经典排序算法及其 Java 实现
  • 你不可错过的前端面试题(一)
  • 排序算法之--选择排序
  • 前言-如何学习区块链
  • 微信小程序--------语音识别(前端自己也能玩)
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 写代码的正确姿势
  • 再谈express与koa的对比
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​决定德拉瓦州地区版图的关键历史事件
  • #### go map 底层结构 ####
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (52)只出现一次的数字III
  • (笔试题)分解质因式
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (六)Hibernate的二级缓存
  • (十六)Flask之蓝图
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • ***详解账号泄露:全球约1亿用户已泄露
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .NET Core Web APi类库如何内嵌运行?
  • .NET Micro Framework初体验
  • .NET 常见的偏门问题
  • .NET 的程序集加载上下文