Ujj*_*ngh 5 c c++ scope include c-preprocessor
限制#define标签范围和避免不必要的令牌冲突的正确策略是什么?
在以下配置中:
MAIN.C
# include "Utility_1.h"
# include "Utility_2.h"
# include "Utility_3.h"
VOID Main() { ... }
Run Code Online (Sandbox Code Playgroud)
Utility_1.h
# define ZERO "Zero"
# define ONE "One"
BOOL Utility_1(); // Uses- ZERO:"Zero" & ONE:"One"
Run Code Online (Sandbox Code Playgroud)
Utility_2.h
# define ZERO '0'
# define ONE '1'
BOOL Utility_2(); // Uses- ZERO:'0' & ONE:'1'
Run Code Online (Sandbox Code Playgroud)
Utility_3.h
const UINT ZERO = 0;
const UINT ONE = 1;
BOOL Utility_3(); // Uses- ZERO:0 & ONE:1
Run Code Online (Sandbox Code Playgroud)
注: Utility _1,Utility_2并Utility_3已经独立编写
错误:宏重新定义和令牌冲突
另外,最令人担心的是:编译器没有指出替换更换令牌的内容
{编辑} 注意:这是一个通用的问题所以请:不建议enum或const
即做什么时候:我必须使用#define&_Please评论我提出的解决方案.. __
Luc*_*ore 12
正确的策略是不使用
#define ZERO '0'
#define ONE '1'
Run Code Online (Sandbox Code Playgroud)
一点都不 如果您需要常量值,请使用,在这种情况下const char,包含在命名空间中.
有两种类型的#define宏:
其中一个只需要在一个单一的文件。让我们称他们为Private #defines
例如。PI 3.14在这种情况下:
按照标准做法:正确的策略是放置#define标签 - 仅在实现中,即。c, 文件而不是头h文件。
多个文件需要的另一个:让我们称之为Shared #defines
例如。EXIT_CODE 0x0BAD在这种情况下:
只#define在头h文件中放置这些通用标签。
此外,尝试使用或类似的约定来唯一地命名标签False NameSpaces,MACRO_例如在标签前加上eg:#define MACRO_PI 3.14以便减少碰撞的概率
#defines没有与C++代码对应的范围; 你无法限制它.它们是天真的文本替换宏.想象一下,"当用grep替换文本时,如何限制范围?"
你应该尽可能地避免它们,而不是使用真正的C++类型.
正确使用宏将通过命名约定几乎自己解决这个问题.如果宏被命名为对象,它应该是一个对象(而不是宏).问题解决了.如果宏被命名为函数(例如动词),它应该是一个函数.
这适用于文字值,变量,表达式,语句......这些都不应该是宏.这些是可以咬你的地方.
在其他情况下,当您使用某种类型的语法助手时,您的宏名称几乎肯定不符合其他任何命名约定.所以问题几乎消失了.但最重要的是,当命名发生冲突时,需要成为宏的宏将导致编译错误.
限制#define范围和避免无法解决的令牌冲突的正确策略是什么.
除非真的有必要,否则请避免使用宏.在C++中,通常可以使用常量变量和内联函数.它们具有键入的优点,并且可以在命名空间,类或代码块中进行范围限定.在C中,需要更频繁地使用宏,但在引入之前要仔细考虑替代方案.
使用命名约定可以清楚地表明哪些符号是宏,哪些符号是语言级标识符.保留ALL_CAPITALS专用宏的名称是很常见的; 如果你这样做,那么宏只能与其他宏发生冲突.这也吸引了更多可能存在漏洞的代码部分.
在每个宏名称上包含一个"伪命名空间"前缀,以便来自不同库/模块/任何内容的宏和具有不同目的的宏不太可能发生冲突.因此,如果您正在设计一个想要为数字零定义字符常量的狡猾库,请将其称为类似DODGY_DIGIT_ZERO.只是ZERO可能意味着很多东西,而且很可能由不同的狡猾库中定义一个零值不断发生冲突.
一些选择:
对宏与普通标识符使用不同的大小写约定.
const UINT Zero = 0;
通过在宏中添加模块名称伪造命名空间:
#define UTIL_ZERO '0' #define UTIL_ONE '1'
在可用的地方(C++),完全沟通宏并使用真正的命名空间:
namespace util {
const char ZERO = '0';
const char ONE = '1';
};