是否可以在不使用“ undef”的情况下重新定义宏?

时间:2019-06-11 08:29:52

标签: c++ c libspatialindex

我试图理解libspatialindex源代码。作为C ++的新手,我很难理解宏的概念。 库的C语言API包装器sidx_api.cc直接和间接包括许多标头,其中两个看似定义了同一宏,涉及到与动态库的接口,而没有'undef':

Tools.h

45 #if (defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64) && !defined __GNUC__
46  #ifdef SIDX_DLL_EXPORT
47  #define SIDX_DLL __declspec(dllexport)
48  #else
49  #define SIDX_DLL __declspec(dllimport)
50  #endif
51 
52  // Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html
53 #pragma warning( disable: 4251 )
54 
55 #else
56  #define SIDX_DLL
57 #endif

sidx_export.h

29 #pragma once
30 
31 #ifndef SIDX_C_DLL  
32 #if defined(_MSC_VER)
33 # define SIDX_C_DLL __declspec(dllexport)
34 # define SIDX_DLL __declspec(dllexport)
35 #else
36 # if defined(USE_GCC_VISIBILITY_FLAG)
37 # define SIDX_C_DLL __attribute__ ((visibility("default")))
38 # define SIDX_DLL __attribute__ ((visibility("default")))
39 # else
40 # define SIDX_C_DLL
41 # define SIDX_DLL
42 # endif
43 #endif
44 #endif

我认为重新定义没有'undef'的宏是有问题的,例如,如herehere所述。 我在这里想念什么吗? 谢谢。

2 个答案:

答案 0 :(得分:2)

如果重新定义它,则需要使用完全相同的预处理令牌列表来重新定义它。对于函数宏和对象宏都是如此。

来自6.10.3 Macroreplacement p2

  

当前定义为类对象宏的标识符不应由另一个#define预处理指令重新定义,除非第二个定义是类对象宏定义并且两个替换列表相同。< / p>      

同样,当前定义为类似函数的宏的标识符不应由另一个#define预处理指令重新定义,除非第二个定义是具有相同编号和拼写的类似函数的宏定义参数,并且两个替换列表相同。

因此,此定义使用shall

现在,从4.Conformance p2

  

如果违反了约束外部出现的“应”或“不应当”的要求,则该行为是不确定的。

这是官方定义。因此,在重新定义宏符号之前,无需将宏符号从预处理器的环境中删除(使用#undef),就可以得到未定义的行为。

如果在C的某些实现中发现其他情况,则这不是标准化的。

正确地,您将在外部设置的某些条件的函数中插入不同的定义:

#if COND
#define M M1
#else
#define M M2
#endif

如果您使用一些重新定义它的库,请确保有一些宏可以设置COND并使它们定义得很好。您需要学习如何使用该库。用不同的pp令牌列表重新定义它是无效的。

答案 1 :(得分:2)

这里没有非法重新定义宏。可以使用相同的定义多次定义一些,这是可以的。造成问题的是不完全相同的定义。

DLL本身始终使用由项目设置定义的SIDX_DLL_EXPORT构建。无需定义此宏即可构建使用DLL的代码。

第二个标头是DLL的一部分。始终在定义SIDX_DLL_EXPORT的情况下进行编译。因此,由它定义的宏(如果有)始终与第一个标头中定义的宏相同。这样相同的重新定义不构成问题。