【C/C++】防止不必要的局部宏替换

简介: 如何避免和防止宏定义在不必要的位置进行替换

【C/C++】防止不必要的局部宏替换

避免和防止宏定义在不必要的位置进行替换。

1. - 问题分析

宏定义为纯文本替换,防止宏替换只能使用 #undef , 并且为了避免影响到其他的代码又需要 重新定义出来。

#if defined(_WIN32) || defined(WIN64) || defined(_MSC_VER)
#define SPRINTF sprintf_s
#elif defined(__linux__) || defined(__GNUC__)
#define SPRINTF sprintf
#endif


#ifdef SPRINTF
#undef SPRINTF
#endif

// redefine 
// ...

但这种方法非常麻烦。

2. - 具体背景

由于项目跨平台为了更好的适配代码,在某些平台下使用了宏。

#define sprintf _sprintf

为了较方便的操作 json ,项目使用了 nlohmann/json ,

项目位置 :https://github.com/nlohmann/json

json.hpp 中,这句话就会与跨平台的文件产生问题

(std::snprintf)(cs.data(), cs.size(), "<U+%.4>", static_cast<unsigned char>(c));

编译时报错

C2039 “_snprintf”: 不是“std”的成员 (编译源文件:D:\xxxx\...\xxx.cpp)

3. - 解决方案

需要在会替换的地方添加上 #pragma push_macro#pragma pop_macro 预编译指令,示例如下:

#define X  1
#pragma push_macro("X")
#undef X
#define X -1
#pragma pop_macro("X")
int x [X];

#pragma push_macro 用于保存 (save) 宏定义
#pragma pop_macro 用于还原 (restore) 宏定义

替换:

#pragma push_macro("snprintf")
#undef snprintf
(std::snprintf)(cs.data(), cs.size(), "<U+%.4>", static_cast<unsigned char>(c));
#pragma pop_macro("snprintf")

这样也不会影响到其他需要使用该宏的代码。

4. - 其他链接


扩展阅读


参考链接

目录
相关文章
|
编译器 Linux C++
【C++ 跨平台开发 】掌握 C++ 跨平台关键宏的使用
【C++ 跨平台开发 】掌握 C++ 跨平台关键宏的使用
322 3
|
存储 缓存 安全
【cmake 生成配置文件】CMake与现代C++:配置文件宏的深度探索与应用
【cmake 生成配置文件】CMake与现代C++:配置文件宏的深度探索与应用
518 0
|
存储 程序员 编译器
在C++语言中局部对象
在C++语言中局部对象
149 0
|
存储 算法 编译器
C/C++编译器局部优化技术:局部优化是针对单个函数或基本块进行的优化
C/C++编译器局部优化技术:局部优化是针对单个函数或基本块进行的优化
456 0
|
存储 算法 安全
04-📝C++核心语法|面向对象2【友元、内部类与局部类、强化训练(数组类封装)、运算符重载、仿函数、模板、类型转换、 C++标准、错误&&异常、智能指针】
复习`C++核心语法`,且适当进行汇编探索底层实现原理,进一步夯实基础,为以后的`底层开发`、`音视频开发`、`跨平台开发`、`算法`等方向的进一步学习埋下伏笔。
04-📝C++核心语法|面向对象2【友元、内部类与局部类、强化训练(数组类封装)、运算符重载、仿函数、模板、类型转换、 C++标准、错误&&异常、智能指针】
|
安全 编译器 C语言
【C++ 编译器 版本支持】深度解读C++ 版本以及编译器版本相关宏
【C++ 编译器 版本支持】深度解读C++ 版本以及编译器版本相关宏
308 0
|
存储 Linux API
C++新特性 线程局部存储
C++新特性 线程局部存储
383 0
|
编译器 Android开发 C++
[√]build.gradle,mk,c++预处理宏联动关系
[√]build.gradle,mk,c++预处理宏联动关系
228 0
|
C++
C++宏 #与##的区别
C++宏 #与##的区别
108 0