1

I have a LOG(fmt, ...) macro that does not work when using a char buf[] as fmt.

The code below is a complete (not actually) working example of the code. In some_function(), I am trying to use LOG() in two different ways but only the first approach works.

To solve the problem, I have tried using #define LOG_STR(x) #x in the following way:

  1. To stringify what is received in the #define LOG by applying LOG_STR() to format like this: LOG_STR(format); and

  2. To apply LOG_STR() directly to the printing like this: LOG(LOG_STR(fmt), 6).

Neither approach works and in fact I get segfault out of it.

    #include <stdio.h>

    #define LOG(format, ...) do {                             \
                fprintf(stderr, "[LOG] " format " [%s]\n",    \
                        ##__VA_ARGS__, __func__);             \
            } while (0)

    static void some_function()
    {
        // This works
        LOG("This is a number: %d", 5);

        // This does not work
        const char fmt[] = "This is a number: %d";
        LOG(fmt, 6);
    }

    int main(void)
    {
        some_function();
        return 0;
    }

When I compile the code above I get the following error:

$ gcc -o log-macro-str log-macro-str.c
log-macro-str.c: In function ‘some_function’:
log-macro-str.c:15:6: error: expected ‘)’ before ‘fmt’
  LOG(fmt, 6);
      ^
log-macro-str.c:4:29: note: in definition of macro ‘LOG’
    fprintf(stderr, "[LOG] " format " [%s]\n",    \
                             ^~~~~~

I'd like to use LOG() in both ways as done in some_function() or without modifiers and just printing a string. I suspect I might have to stringify the format part but I can't seem to do it correctly.

What am I doing wrong, and how can I solve this issue?

1 Answer 1

5

The stringify operator, # in a macro, converts preprocessor tokens to text in a string literal. It will not change the contents of a char buffer to a compile-time string literal.

To make your macro work, use multiple fprintf statements:

#define LOG(format, ...) do {                          \
            fprintf(stderr, "[LOG] ");                 \
            fprintf(stderr, format, __VA_ARGS__);      \
            fprintf(stderr, " [%s]\n", __func__);      \
        } while (0)
Sign up to request clarification or add additional context in comments.

3 Comments

The important point is that the stringify operator and the string literal concatenation are compile-time operations while the char buffer is a runtime entity, hence this can't possibly work. You can't concatenate a string at compile time that is not yet known.
I was hoping to use a single fprintf but I now understand (from the answer and comment above) why this isn't possible.
@Daniel Well, it is possible to do with a single fprintf, but what you'd have to do to accomplish it would make it an ugly solution that I can't say that I'd recommend over this one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.