1

I have the following code:

#define MAX_NAME_LEN 15
#define PRINT_CELL(x) \
    printf("|%" #MAX_NAME_LEN "s|", #x);

When I try to compile, I get the following error:

main.c:9:21: error: '#' is not followed by a macro parameter
    9 | #define PRINT_CELL(x) \
      |                     ^

I'm not quite sure what I did wrong. How do I fix this?

nswerhun
  • 144
  • 8
  • 1
    §6.10.3.2 p1: *"Each # preprocessing token in the replacement list for a function-like macro shall be followed by a parameter as the next preprocessing token in the replacement list."* – user3386109 Nov 21 '20 at 03:02
  • 1
    In other words, you can only use it with arguments to that macro, not with other arbitrary names. – Shawn Nov 21 '20 at 03:03

2 Answers2

3

#MAX_NAME_LEN is illegal because MAX_NAME_LEN is not an identifier in the replacement list of the PRINT_CELL(x) macro. Use the following, instead:

#define PRINT_CELL(x) printf("|%*s|", MAX_NAME_LEN, #x);
dxiv
  • 16,984
  • 2
  • 27
  • 49
  • 1
    Don't use the `;` or you'll incurr in errors most of the time. – Luis Colorado Dec 01 '20 at 06:56
  • @LuisColorado That's a good point, and there are a number of alternatives discussed under [Why use apparently meaningless do-while and if-else statements in macros?](https://stackoverflow.com/questions/154136/why-use-apparently-meaningless-do-while-and-if-else-statements-in-macros) for example. That said, in this case the `;` was in OP's code and I left it there because it's not related to the main point of the question. – dxiv Dec 01 '20 at 07:07
  • it's generally more C style to take it off, so if you need it you can allways say `PRINT_CELL(ARGUMENT);` but what if you have `if (a) PRINT_CELL(ARGUMENT); else b();` will generate a syntax error, as the `if` statement will end with the second `;` token. That's the same problem as with the idiom `#define PRINT_CELL(arg) do{ printf(bla bla); } while (0)` (without the last semicolon) – Luis Colorado Dec 01 '20 at 16:11
2

The #x is fine because x is a macro argument.

But, #MAX_NAME_LEN is not fine because MAX_NAME_LEN is not a macro argument

You can fix this with an extra "helper" macro:

#define MAX_NAME_LEN 15

#define STRINGIFY(s) \
    #s

#define PRINT_CELL(x) \
    printf("|%" STRINGIFY(MAX_NAME_LEN) "s|", #x);

That solves the complaint from cpp, but the result compiles with an error because the output produces a complaint about the format string for printf:

int
main(void)
{
 printf("|%" "MAX_NAME_LEN" "s|" "hello");
 return 0;
}

To solve that, change: % to %%:

#include <stdio.h>

#define MAX_NAME_LEN 15

#define STRINGIFY(s) \
    #s

#define PRINT_CELL(x) \
    printf("|%%" STRINGIFY(MAX_NAME_LEN) "s|" #x "\n");

int
main(void)
{

    PRINT_CELL(hello)

    return 0;
}

But, when we run that version, the output of program is:

|%MAX_NAME_LENs|hello

What I suspect you're trying to do can be accomplished better using the * modifier of %s:

#include <stdio.h>

#define MAX_NAME_LEN 15

#define STRINGIFY(s) \
    #s

#define PRINT_CELL(x) \
    printf("|%*s\n",MAX_NAME_LEN,#x);

int
main(void)
{

    PRINT_CELL(hello)

    return 0;
}

The output of this is:

|          hello
Craig Estey
  • 30,627
  • 4
  • 24
  • 48