2

I created the below program:

#include<stdio.h>
#include<stdlib.h>

#define TESTER "name=%s "

int main(){
    char *x;
    x = malloc(100);
    snprintf(x, 100, "Heyaa tester %s", TESTER, "hello");
    printf("%s", x);
    free(x)
    return 0;
}

I am basically trying to get the output something like - "Hey tester name=hello", However, it seems to be like below:

Heyaa tester name=%s

Do I need to append hello initially to the macro and then do snprintf to the malloc'd variable.

Thanks.

RatDon
  • 3,403
  • 8
  • 43
  • 85
wonder
  • 885
  • 1
  • 18
  • 32
  • 2
    This will not work as you intended. This is practically `snprintf(x, 100, "Heyaa tester %s", "name=%s ", "hello");`. So you substitute the first `%s` with `"name=%s "` and the `"hello"` is basically ignored. What you could do is `snprintf(x, 100, "Heyaa tester"TESTER, "hello");` – Eraklon Mar 27 '20 at 11:32

2 Answers2

4

You need to include the macro as part of the format specifier of snprintf() where it expands to "name=%s " at the time of pre-processor itself and the concatenated string "Heyaa tester name=%s" is created. What you have in the OP, makes name=%s as a literal string that will undergo %s formatting treatment by snprintf()

snprintf(x, 100, "Heyaa tester " TESTER, "hello");

Your original attempt should have been caught as suspicious, if you enabled extra warnings flag in your compiler as printf() would have thrown a warning too many arguments but not enough specifiers found ([-Wformat-extra-args] with gcc).

And as a better coding practice always clean up the memory allocated dynamically by the program instead of letting the OS doing it and always compile your program with extra warning flags.

Inian
  • 80,270
  • 14
  • 142
  • 161
2

As @Eraklon pointed out, though the Macro is expanded in the pre-processor, it's attached to the format specifier during compilation.

You can modify that line to the below and this will work.

snprintf(x, 100, "Heyaa tester " TESTER, "hello");

Here, the macro is expanded in pre-processor, then we are doing a string concatenation and after that the format specifier will pick up "hello" during compilation.

Just FYI: Macro and string, string and string, macro and macro can be concatenated just using a space in between. The compiler treats adjacent strings as single string. But beware it won't work with a string variable.

For further reading: C/C++ macro string concatenation

RatDon
  • 3,403
  • 8
  • 43
  • 85
  • "Token pasting" is the use of the `##` preprocessor operator to create a new token. The rest of those things are not token pasting. And string concatenation is performed *after* preprocessing. – rici Mar 27 '20 at 13:43
  • @rici Thanks for the info. Edited the answer. – RatDon Mar 29 '20 at 05:23