Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printf format specifier and fields outside quotes

Tags:

c

printf

I came across the following code:

#define ERROR 0
#define WARN 1
#define INFO 2
#define DEBUG 3  

extern int log_level;

char const *LEVEL_TO_STRING[] = { "ERROR", "WARN", "INFO", "DEBUG" };

#define LOG(level, s, ...)                                                  \
    do                                                                      \
    {                                                                       \
        if(level <= log_level)                                              \
            printf( "[%s] " s "\n", LEVEL_TO_STRING[level], ##__VA_ARGS__)  \
    }                                                                       \
    while(0)                                                                \   

I do not understand what the s is doing outside the quotes in the printf statement. I tried searching for what this is and how it works, but I'm not sure what to look for. Could someone explain to me how this code works?

As a follow-up, is it possible to write code like the example above outside a macro? The closest I've seen to this is using format specifiers:

#define FORMAT "ld"
long num = 1000000;
printf("%" FORMAT "\n", num);

It would help to understand how these two cases work internally, and why C does not let me do something like, printf("%s" s "\n", string1, string2) as is done in the macro above.

EDIT : Not a clean dup of How does concatenation of two string literals work? because this post is specific to printf (and format specifiers) as it relates to macros. Also, there is useful information in the responses to this post that isn't available in the other.

like image 713
aspen100 Avatar asked Mar 22 '26 01:03

aspen100


1 Answers

I do not understand what the s is doing outside the quotes in the printf statement

In order to see what happens you need to recall that s is replaced with the second parameter of LOG macro in the text of the program. The only way that this could work is when s is a string literal, because C merges them. In other words, there is no difference between

"quick brown fox"

and

"quick" " brown " "fox"

These two forms of writing a string literal are equivalent.

In the same way, passing "ld" to FORMAT in

printf("%" FORMAT "\n", num);

is equivalent to

printf("%ld\n", num);

and is legal.

why C does not let me do something like, printf("%s" s "\n", string1, string2) as is done in the macro above?

Passing anything other than a string literal is illegal:

char FORMAT[] = "ld";
printf("%" FORMAT "\n", num); // <<== Does not compile

s and FORMAT in your code must be not just strings, but string literals:

#define s "[%s]"
...
printf("%s" s "\n", string1, string2); // This compiles
like image 197
Sergey Kalinichenko Avatar answered Mar 24 '26 16:03

Sergey Kalinichenko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!