2

我正在尝试理解libspatialindex源代码。作为 C++ 的新手,我很难理解宏的概念。该库的 C API 包装器sidx_api.cc直接和间接地包括许多头文件,其中两个似乎定义了相同的宏,涉及与动态库的接口,没有“undef”:

工具.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”的宏是有问题的,例如,如这里这里所讨论的。我在这里错过了什么吗?谢谢。

4

2 回答 2

3

此处没有非法重新定义宏。有些可能会以相同的定义多次定义,这没关系。构成问题的是不同的定义。

DLL 本身始终SIDX_DLL_EXPORT由项目设置定义。使用 DLL 的代码是在未定义此宏的情况下构建的。

第二个标头是 DLL 的一部分。它总是SIDX_DLL_EXPORT在定义时编译。因此,由它定义的宏,如果有的话,总是与第一个头文件中定义的相同。这种相同的重新定义不构成问题。

于 2019-06-11T09:52:44.307 回答
2

如果您重新定义它,您需要使用完全相同的预处理标记列表重新定义它。这适用于函数宏和对象宏。

来自 6.10.3 Macroreplacement p2

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

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

所以这个定义使用shall.

现在,从4.Conformance p2

如果违反了出现在约束之外的“应”或“不应”要求,则行为未定义。

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

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

正确的做法是根据您在外部设置的某些条件插入不同的定义:

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

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

于 2019-06-11T09:22:10.763 回答