【问题标题】:Mixing C/C++ using macros and C style strings使用宏和 C 样式字符串混合 C/C++
【发布时间】:2012-12-14 08:27:39
【问题描述】:
gcc/g++ 4.7.2
CXXFLAGS -Wall -Wextra -g -O2

你好,

我有这个使用 C 风格编写的头文件 (mu_test.h)。它包含以下marcos

#define GET_ERROR() ((errno == 0) ? "None" : strerror(errno))

#define LOG_ERR(fmt, ...) fprintf(stderr, "[ERROR] %s:%d: errno: %s " fmt "\n", __func__, __LINE__, GET_ERROR(), ##__VA_ARGS__)

#define MU_ASSERT(test, msg) do {               \
        if(!(test)) {                           \
            LOG_ERR(msg);                       \
            return msg;                         \
        }                                       \
    } while(0)

我有一个使用 g++ 编译的 cpp 文件 (floor_plan_src.cpp),其中包含 mu_test.h

#include "mu_test.h"
char* test_memory_allocation()
{
    plan = new floor_plan();

    MU_ASSERT(plan != NULL, "Failed to allocate memory for floor_plan");

    return NULL;
}

我收到此警告:

deprecated conversion from string constant to ‘char*’

所以我传递给类似函数的 marco 的字符串常量不喜欢它(C 字符串),因为我使用 g++ 编译了我的源代码。

我认为这个问题与混合 c/c++ 有关。

解决方案 1:将 mu_test.h 中的所有宏用 extern "C" 包装

#ifdef __cplusplus
extern "C"
{
#endif /* _cplusplus */
#define GET_ERROR() ((errno == 0) ? "None" : strerror(errno))

#define LOG_ERR(fmt, ...) fprintf(stderr, "[ERROR] %s:%d: errno: %s " fmt "\n", __func__, __LINE__, GET_ERROR(), ##__VA_ARGS__)

#define MU_ASSERT(test, msg) do {               \
        if(!(test)) {                           \
            LOG_ERR(msg);                       \
            return msg;                         \
        }                                       \
    } while(0)
#ifdef __cplusplus
}
#endif /* __cplusplus */

解决方案 1 仍然给了我同样的警告。

解决方案2:将头文件包装在 floor_plan_src.cpp 中

extern "C" {
#include "mu_test.h"
}

解决方案 2 仍然给了我同样的警告

解决方案 3:包装函数

extern "C" char* test_memory_allocation()
{
    plan = new floor_plan();

    MU_ASSERT(plan != NULL, "Failed to allocate memory for floor_plan");

    return NULL;
}

方案3同上

解决方案 4: 尝试将常量字符串转换为非 const char*

MU_ASSERT(plan != NULL, (char*)"Failed to allocate memory for floor_plan");

出现以下错误:

 expected primary-expression before char
"[ERROR] %s:%d: errno: %s " cannot be used as a function

非常感谢您的任何建议,

【问题讨论】:

  • 你需要##中的##__VA_ARGS__
  • 这是避免尾随逗号所必需的,即没有它就无法工作。 LOG_ERR("错误发生");因为我没有传递任何论据。
  • 您在MU_ASSERT 中使用LOG_ERR 有点危险,如果msg 意外包含格式说明符,它会崩溃并烧毁。你可能应该这样称呼它:LOG_ERR("%s", msg);.

标签: c++ c


【解决方案1】:

问题是您的 test_memory_allocation 可能会返回一个字符串文字,并且您不应该将字符串文字衰减为非 const char*:它在 C++ 中是允许的,但仍然不推荐使用。

您的代码扩展为:

char* test_memory_allocation()
{
    plan = new floor_plan();

    do {
        if(!(plan != NULL)) {
            LOG_ERR("Failed to allocate memory for floor_plan")
            return "Failed to allocate memory for floor_plan";
        }
    } while(0);

    return NULL;
}

要修复它,您只需要让test_memory_allocation 返回一个const char*,否则您可以返回一个指向可能衰减为非常量char* 的指针(例如静态char 数组或堆分配的内存区域)。

extern "C" 仅用于避免 C++ 名称混淆,它只影响函数,而不影响宏。

【讨论】:

  • 你好 Peoro。那么在这种情况下使用外部“C”是没有意义的呢?我通过转换为 (char*) #define MU_ASSERT(test, msg) do { \ if(!(test)) { \ LOG_ERR(msg); 解决了这个问题\返回(字符*)消息; \ } \ } while(0)
  • @ant2009:这是没有意义的,因为 a)它不会改变语言(只有链接)和 b)它在 C 中也是未定义的行为。
  • @ant2009 不要将const char* 转换为char*,您应该将test_memory_allocation() 的返回类型更改为const char*。也就是说,如果你能做到的话。如果它是固定 API 的一部分,那么您不能...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 2017-04-18
  • 2011-07-12
  • 2017-08-31
  • 2015-01-13
  • 2011-08-16
相关资源
最近更新 更多