1

I see this interesting question here asking for the possibility of a program without main(). There, I saw eon giving one answer as follows, which works well in C/C++.

#include<stdio.h>
#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)

int begin()
{
  printf(" hello ");
}

Can someone explain how the above code works? Isn't really there a main() here or just hiding it from our eyes archly?

Community
  • 1
  • 1
herohuyongtao
  • 49,413
  • 29
  • 133
  • 174
  • 8
    Oh, please don't do that :(. That's only code obfuscation. `decode` will glue some characters together, and `begin` simply uses `decode` to glue `m` `a` `i` `n` together to `main`. – Zeta Dec 28 '13 at 16:55
  • 2
    Do you know how the preprocessor works? Specifically, the `##` operator? – Oliver Charlesworth Dec 28 '13 at 16:55
  • Run `gcc -E` on the program to see what the preprocessor does – Guido Dec 28 '13 at 16:59
  • Why write code that is difficult to understand? Seems rather silly and a nightmare to maintain – Ed Heal Dec 28 '13 at 17:10

4 Answers4

10

Have a close look at the macro: it just spliced together main from the characters in animate and gets them replaced for begin().

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
4

After the macro substitution:

#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)

begin becomes decode(a,n,i,m,a,t,e), which then becomes main. There you have it.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
2

The compiler doesn't see "begin" whatsoever. It's completely substituted by the time it gets to the compiler, because macros are simply text-substitutions. Perhaps a helpful diagram to add on to the other great answers.

#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)

Take a look at m, and see where m is in the argument list.

decode(s,t,u,m,p,e,d)
             ^
             | 
decode(a,n,i,m,a,t,e)

Therefore the first letter is m => m. Then repeat the process, s => a, u => i, t => n.

decode(s,t,u,m,p,e,d)
       ^ ^ ^   
       | | |
decode(a,n,i,m,a,t,e)

Then the resulting letters are "pasted" together with token concatenation, and it looks like main as far as the compiler is concerned.

1

This works because the compiler doesn't really see int begin(){}, The preprocessor will replace begin with main after performing macro substitution and concatenation operator.

First The preprocessor will replace begin with decode(a,n,i,m,a,t,e), after that it will do a rescanning on the replacement list for further replacement, it will find function-like macro decode which will be replaced by it's replacement list after performing the concatenation operator, like this:

m##a##i##n => main

So the compiler will only see the preprocessor output which contain int main(){} and not int begin(){} thus legal code.

AlexDan
  • 3,203
  • 7
  • 30
  • 46