1

I found the following snippet of code .

#define f(g,g2) g##g2
main() {

    int var12=100;
    printf("%d",f(var,12));

}

I understand that this will translate f(var,12) into var12 .

My question is in the macro definition, why didn't they just write the following :

#define f(g,g2) gg2

why do we need ## to concatenate text, rather than concatenate it ourselves ?

Ait-Gacem Nabil
  • 165
  • 3
  • 12

2 Answers2

4

If one writes gg2 the preprocessor will perceive that as a single token. The preprocessor cannot understand that that is the concatenation of g and g2.

user3386109
  • 34,287
  • 7
  • 49
  • 68
Zois Tasoulas
  • 1,242
  • 1
  • 11
  • 23
  • Are you saying that `##` is not an escaped `#` here? – Robert Harvey Aug 21 '21 at 17:14
  • 3
    @RobertHarvey No, a single hash is the stringification operator. A double hash is the concatenation operator. They are two entirely different operators. Much the same way that `-x` and `--x` mean two entirely different things. – user3386109 Aug 21 '21 at 17:18
  • So escaping a hash is a context-sensitive operation? – Robert Harvey Aug 21 '21 at 17:18
  • 1
    @RobertHarvey I don't know what language you're thinking about. There is no method to escape a hash in the C preprocessor (except by hacks and misdirection). See for example [this question](https://stackoverflow.com/questions/38244660/how-to-escape-a-in-a-macro). – user3386109 Aug 21 '21 at 17:21
2
   #define f(g,g2) g##g2

My opinion is that this is poor unreadable code. It needs at least a comment (giving some motivation, explanation, etc...), and a short name like f is meaningless.

My question is in the macro definition, why didn't they just write the following :

#define f(g,g2) gg2

With such a macro definition, f(x,y) would still be expanded to the token gg2, even if the author wanted the expansion to be xy

Please take time to read e.g. the documentation of GNU cpp (and of your compiler, perhaps GCC) and later some C standard like n1570 or better.

Consider also designing your software by (in some cases) generating C code (inspired by GNU bison, or GNU m4, or GPP). Your build machinery (e.g. your Makefile for GNU make) would process that as you want. In some cases (e.g. programs running for hours of CPU time), you might consider doing some partial evaluation and generating specialized code at runtime (for example, with libgccjit or GNU lightning). Pitrat's book on Artificial Beings, the conscience of a conscious machine explains and arguments that idea in an entire book.

Don't forget to enable all warnings and debug info in your compiler (e.g. with GCC use gcc -Wall -Wextra -g) and learn to use a debugger (like GNU gdb).

On Linux systems I sometimes like to generate some (more or less temporary) C code at runtime (from some kind of abstract syntax tree), then compile that code as a plugin, and dlopen(3) that plugin then dlsym(3) inside it. For a stupid example, see my manydl.c program (to demonstrate that you can generate hundreds of thousands of C files and plugins in the same program). For serious examples, read books.

You might also read books about Common Lisp or about Rust; both have a much richer macro system than C provides.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 2
    I looked at N1570, and it's nearly eight hundred pages long. Does the OP really need to know all of that to suss out `##`? – Robert Harvey Aug 21 '21 at 17:23
  • I guess the OP could buy a shorter book about C programming. My recommendation is to go to some university and follow courses about C programming - human teachers are often better than just reading books – Basile Starynkevitch Aug 21 '21 at 17:23