1

I am wondering if it's possible to use a C pre-processing define to change a string format specifier. I've tried writing the following, but seem to get a compiler error. It's simply trying to replace the existing format specifiers with the correct one.

#include <stdio.h>

//This is the problem line....
#define %d %llu    

int main(int argc, char** argv){
    unsigned long long int myInt = 0;

    printf("myInt start value: %d", myInt++);
    printf("myInt value=%d (that got incremented)", myInt++);
    printf("myInt value: %d; wow, another post-increment", myInt++);
    printf("myInt final value %d", myInt);

    return 0;    
}

I get the following compiler error:

error: expected an identifier
  #define %d %llu
          ^

Why is this syntax not acceptable? Is it even possible to accomplish?

  • 4
    1. You cannot name a macro with `%d` - it's not a legal C identifier. 2. Even if you could - macros are not replaced in C string literals. 3. For every variation of `int` type, there are matching formatters which are correctly interpreted on the resp. platform. Hence, this macro trick shouldn't be even necessary. – Scheff's Cat May 29 '18 at 14:35
  • That's not how macros work. Besides obeying the same rules as C for symbol names, you do macro substitution inside string literals. – Some programmer dude May 29 '18 at 14:35
  • Aside: `%lli` is the wrong format specifier for `unsigned long long`. It should be `%llu`. – Ian Abbott May 29 '18 at 16:05

2 Answers2

3

What you want to do is not possible.

Macros are not replaced within string literals and the rules for valid identifier names also apply for macro names.

What you could do is something like this:

#if xyz
  #define FMT   "%d"
#else
  #define FMT   "%lli"
#endif

....

printf("myInt start value: " FMT "\n", myInt++);

BTW: Normally you should not need this. For the native types int, long etc. the format specifiers should be usable as normal.

For types with fixed size (e.g. int64_t etc.) there are already macros defined in inttypes.h

Gerhardh
  • 11,688
  • 4
  • 17
  • 39
0

Is it even possible to accomplish? No, its not possible the way you are doing. In statement

#define %d %lli 

macro name must be a valid identifier.

From the C99 standard

section 6.10.1

# define identifier replacement-list new-line

and from 7.1.13

  • All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
  • All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.
  • Each macro name in any of the following subclauses (including the future library directions) is reserved for use as specified if any of its associated headers is included; unless explicitly stated otherwise (see 7.1.4).

Make the macro-name as a valid identifier. for e.g define the macro as

#define INT_FMT "%d"

and then

 int myInt = 10;
 printf("myInt start value is : "  INT_FMT  "\n", myInt);
Achal
  • 11,821
  • 2
  • 15
  • 37