【问题标题】:how to avoid name conflicts coming from #define in C? (or C++)如何避免来自 C 中的#define 的名称冲突? (或 C++)
【发布时间】:2017-10-08 13:38:31
【问题描述】:

这应该是一个非常基本的问题,我可以通过更改一些名称来避免这种情况,但我认为这里可能缺少一些东西。
我为这个问题做了一个最简单的代码。

conv.h :
  1 struct convpar_ {
  2 int K;
  3 } convpar_;

test.c :
  1 #include <stdio.h>
  2 #include "conv.h"
  3 
  4 #define K 7
  5 
  6 typedef struct convpar_ convpar;
  7 
  8 void func1(convpar cp)
  9 {
 10 printf("cp.K = %d\n", cp.K);
 11 }
 12 
 13 main()
 14 {
 15 convpar cp = {K};
 16 
 17 func1(cp);
 18 }

如果我这样做cc test.c -o test,我会得到

cc     test.c   -o test
test.c: In function 'func1':
test.c:13: error: expected identifier before numeric constant

我知道这是因为我在第 4 行将字符“K”定义为“7”,这使得第 10 行在预处理后出现printf("cp.7" = %d\n", cp.7);。当我将 convpar_ 的成员 K 的名称更改为其他名称(例如 Ki)时,这个问题就消失了。

但有时,当我想定义一个常量并且它恰好是我在定义变量的同一个文件中使用的全局变量或结构的成员变量时,有时会出现这种情况。解决这个问题的正确方法是什么? (这也适用于 C++)

【问题讨论】:

  • C++ 中,您可以使用命名空间。在CC++,可以重命名。
  • 不要使用宏 (#define)。如果您想要一个常量,请使用const(或constexpr)变量(在命名空间中)。
  • 使用#if defind xxx 声明。
  • @JesperJuhl 我可以使用定义宏来定义另一个宏。但是对于 const 类型,不能。我可以在函数中使用 const 类型来定义变量。如果我想声明一个静态数组并且我想使用定义宏上的一些操作来定义数组的大小怎么办?也许我会提出一个新问题..
  • 初始化结构成员的正确语法是convpar cp = { .K = K};,但这也会导致类似的编译错误。

标签: c++ c scope preprocessor


【解决方案1】:

“如何避免命名冲突”的答案通常是:使用专有名称(而不是 K)。此外,对于 C++,use namespacesdon't use using-directives i.e. using namespace

所以代码可能变成这样:

#include <iostream>

namespace MyNamespaceName {
    struct MyStructName {
        int myVariableName;
    };

    // probably even a member function, and struct->class, and member variable private
    void MyFunctionName(MyStructName const& myStructInstanceName) {
        std::cout << "clearStructInstanceName.clearVariableName = "
            << myStructInstanceName.myVariableName
            << '\n';
    }

    static constexpr auto myStaticVariableName = 7;
}

int main() {
    auto const myStructInstanceName =
        ::MyNamespaceName::MyStructName {
            ::MyNamespaceName::myStaticVariableName
        };

    ::MyNamespaceName::MyFunctionName(myStructInstanceName);
}

在大多数情况下,这可能有点矫枉过正,但在处理大型协作项目时,您确实需要保持全局命名空间干净,并考虑到会有其他人认为与您相同的变量名称。

【讨论】:

    【解决方案2】:

    您无法解决此问题,因为这是预处理器的目标:动态修改您的代码。解决方案是采用良好的编码实践:不要将预处理器用于一般编程。此外,使用命名空间的命名规则。什么?将其命名为 CONVERSION_ID_K、CONVERSION_ID_L 等。变量等使用小写。

    【讨论】:

    • 好的,也许这就是一般的答案。我还发现 Jeper Juhl 的评论(使用 const int 而不是#define)很有用。
    • 如果您能就我的新问题给我一个答案/评论,我将不胜感激:stackoverflow.com/questions/43884007/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 2012-07-21
    • 1970-01-01
    • 2011-11-25
    • 1970-01-01
    相关资源
    最近更新 更多