ant2009
ant2009

Reputation: 22566

Mixing C/C++ using macros and C style strings

gcc/g++ 4.7.2
CXXFLAGS -Wall -Wextra -g -O2

Hello,

I have this header file (mu_test.h) that is written using C style. It contain the following 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)

I have a cpp file (floor_plan_src.cpp) compiled using g++ that includes the 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;
}

I get this warning:

deprecated conversion from string constant to ‘char*’

So my string constant that I am passing to that function-like marco doesn't like it (C strings) as I have compiled my source using g++.

I thought this problem was to do with mixing c/c++.

solution 1: wrap all the macros in the mu_test.h with 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 */

Solution 1 still gave me the same warning.

solution 2: wrap the header file in floor_plan_src.cpp

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

Solution 2 still gave me the same warning

Solution 3: wrap the function

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

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

    return NULL;
}

Solution 3 same as above

Solution 4: Try and convert the constant string to a non-const char*

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

gave the following error:

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

Many thanks for any suggestions,

Upvotes: 2

Views: 748

Answers (1)

peoro
peoro

Reputation: 26060

The problem is that your test_memory_allocation might return a string literal, and you shouldn't make a string literal decay to non-const char*: it's allowed in C++, but still deprecated.

Your code gets expanded in:

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;
}

To fix it you just need to make test_memory_allocation return a const char* or otherwise you could return a pointer to something that could decay to a non-const char* (for example a static char array or to a heap-allocated memory area).

extern "C" is only needed to avoid C++ name mangling, it only affects functions, not macros.

Upvotes: 4

Related Questions