4

Is it possible to write a Macro (using token concatenation) that returns format for printf? E.g.

#define STR_FMT(x) ...code-here...

STR_FMT(10) expands to "%10s"

STR_FMT(15) expands to "%15s"

... etc.

So that I can use this macro inside a printf:

printf(STR_FMT(10), "*");
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Andrei Ciobanu
  • 12,500
  • 24
  • 85
  • 118

2 Answers2

14

You can, but I think it might be better to use the capability printf() has to specify the field size and/or precision dynamically:

#include <stdio.h>

int main(int argc, char* argv[])
{
    // specify the field size dynamically
    printf( ":%*s:\n", 10, "*");
    printf( ":%*s:\n", 15, "*");

    // specify the precision dynamically
    printf( "%.*s\n", 10, "******************************************");
    printf( "%.*s\n", 15, "******************************************");

    return 0;
}

This has the advantage of not using the preprocessor and also will let you use variables or functions to specify the field width instead of literals.


If you do decide to use macros instead, please use the # operator indirectly (and the ## operator if you use it elsewhere) like so:

// macros to allow safer use of the # and ## operators
#ifndef STRINGIFY
#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#endif

#define STR_FMTB(x) "%" STRINGIFY(x) "s"

Otherwise if you decide to use macros to specify the field width, you'll get undesired behavior (as described in What are the applications of the ## preprocessor operator and gotchas to consider?).

Community
  • 1
  • 1
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
7
#define STR_FMT(x) "%" #x "s"
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 1
    For future reference, gcc now flags this as a security warning. It's considered unsafe to construct a `printf` substitution using stringification, because mistakes in the macro argument result in binary code that is easily exploited by memory layout attacks. – Byron Hawkins Jun 03 '20 at 10:48