【问题标题】:Library redefines NULL库重新定义 NULL
【发布时间】:2009-11-30 00:44:20
【问题描述】:

我正在使用一个重新定义 NULL 的库。它会导致我程序的其他部分出现一些问题。我不确定我能做些什么。任何的想法?我的程序是 C++,库是 C

#ifdef NULL
#undef NULL
#endif

/**
 * NULL define.
 */
#define NULL    ((void *) 0)

哦,它会产生这些错误:

Generic.h:67: error: default argument for parameter of type 'LCD::LCDBase*' has type 'void*'
Generic.cpp: In constructor 'LCD::Generic::Generic(std::string, Json::Value*, int, LCD::LCDBase*)':
Generic.cpp:44: error: invalid conversion from 'void*' to 'QObject*'
Generic.cpp:44: error:   initializing argument 2 of 'LCD::LCDWrapper::LCDWrapper(LCD::LCDInterface*, QObject*)'
Generic.cpp: In member function 'void LCD::Generic::BuildLayouts()':
Generic.cpp:202: error: invalid conversion from 'void*' to 'LCD::Widget*'
Generic.cpp: In member function 'void LCD::Generic::AddWidget(std::string, unsigned int, unsigned int, std::string)':
Generic.cpp:459: error: invalid conversion from 'void*' to 'LCD::Widget*'
scons: *** [Generic.o] Error 1

这是第一个:

Generic(std::string name, Json::Value *config, int type, LCDBase *lcd = NULL);

编辑:好的,显式转换有效,但是如何转换函数指针?

【问题讨论】:

  • 你有没有试过在包含 NULL 后取消定义它?
  • 我不确定将其重新定义为什么。我尝试在 ORG_NULL 中保存 NULL 并在包含 libvisual 后重新定义 NULL,但这不起作用。
  • 其实我想我只要适当地强制转换 NULL 就可以了。
  • 附带说明:如果可能,请与图书馆作者交流。他们没有充分的理由应该重新定义 NULL - 它已经定义了。如果他们真的需要自己的常量,他们应该给它起个别的名字,这样就不会干扰了。
  • #define ORG_NULL NULL 不保存任何东西,顺便说一句,cpp 不是那么简单:P。您可以使用任何有效的 NULL 定义,例如 0;但是,最好的解决方案仍然是修复库。

标签: c++ c null undefined c-preprocessor


【解决方案1】:

你能在没有这个定义的情况下重建库吗?这就是我首先要尝试的。 NULL 是一个非常标准的宏,应该假定在任何地方都定义了。

现在,您的问题是 C++ 不允许从 void * 自动转换为像 C 那样的其他指针类型。

来自C++ Reference

在 C++ 中,NULL 扩展为 0 或 0L。

如果这不起作用,只需在库中进行全局替换:NULLLIBDEFINEDNULL 或其他东西。这样您就可以保持库代码完整并避免宏冲突。

【讨论】:

  • 我考虑过这一点,但库可能出于内部原因重新定义了它。那将是我尝试的最后一件事。我将尝试适当地转换 NULL。
  • 我在 lib 的 IRC 频道上与某人聊天。他不确定为什么 NULL 被重新定义。我继续将它从库中删除,它编译得很好。
  • 令人着迷。那个属于 DailyWTF!感谢您的更新!
【解决方案2】:

您有权访问该库源吗?如果是这样,我认为对他们的代码进行搜索和替换是有必要的。 (将它们的 NULL 替换为 LIBNAME_NULL 或类似的东西。)如果这根本不是一个选项,那么我建议在您的代码中使用 0 而不是 NULL。

不过,我很好奇:这会导致什么问题?他们没有改变 null 的值,只是改变了默认的转换。

【讨论】:

  • 在 C 中,您可以从 void* 隐式转换为所有指针类型。在 C++ 中你不能。由于库将其定义为 ((void*)0),因此他遇到了 C++ 代码问题。
  • 啊,好点 asveikau。我最近一直在做一些 C 接口,所以我有点陷入这种心态:)
【解决方案3】:

你的一个 cmets 说你考虑过自己重新定义它,但你不知道要重新定义它。

很多实现都会像这样定义NULL:

#undef NULL

#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void*)0)
#endif

这是因为在 C 中,将其作为 void 指针是有意义的,因为它是一种可以隐式转换为其他类型的指针类型。

C++ 不允许这样做(这会导致您的问题),但使用 0 而不是 NULL 可以。

我认为在所有最新版本中,GCC 实际上会将其定义为__null,这是一个不可移植的扩展。

【讨论】:

    【解决方案4】:

    最通用的方法是包装有问题的包含,storerestore 宏之前的定义。但是,这取决于编译器。
    这就是你可以用 VC 做到的方式:

    #pragma push_macro("NULL")
    #include <offendinglib.h>
    #pragma pop_macro("NULL")
    

    或者,将宏设置为您之后需要的:

    #include <offendinglib.h>
    #undef NULL
    #define NULL 0
    

    【讨论】:

      【解决方案5】:

      是的,您只需要适当地投射:

      Generic(std::string name, Json::Value *config, int type,
          LCDBase *lcd = (LCDBase *)NULL);
      

      【讨论】:

      • 您不应该需要在 C++ 中从 NULL 转换为 T*
      • gf,但该库重新定义了 NULL,因此它不会隐式转换。
      • 坏主意。错过了 NULL 宏的要点。如果您编写的代码强制转换为 NULL,人们会看到您的代码并认为您很愚蠢。 :-)
      • 如果我没有混淆任何内容:库在 C 中并在标题中重新定义,问题似乎是由于将 C 库包含到 C++ 代码中造成的。
      • 听起来图书馆是“罪魁祸首”,所以修复图书馆。不要为了“修复”库的问题而弄乱所有自己的代码。
      猜你喜欢
      • 2011-07-05
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2012-08-21
      • 1970-01-01
      • 2021-10-21
      • 1970-01-01
      相关资源
      最近更新 更多