Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C strange macro syntax

Tags:

I found this C code example, and I am absolutely puzzled:

#include <stdio.h> #define M(a,b) a%:%:b  main() {   int a=1, b=2, ab[]={10,20}, c;   printf( "%d", M(a,b)<:a:> );   printf( "%d", M(a,b)<:a:>?a:b );   printf( "%d", c=M(a,b)<:a:>?a:b ); } 

Could someone explain what this is supposed to do? It doesn't even compile in Visual Studio, but I ran it online (on ideone.com) and it printed 2011, which also added to the confusion.

like image 209
Eutherpy Avatar asked May 01 '16 23:05

Eutherpy


1 Answers

It's making use of C digraphs which were amendments to the C standard in 1994 and therefore part of the C99 standard. Swapping the digraphs out with their actual characters, you get:

#include <stdio.h> #define M(a,b) a##b  main() {   int a=1, b=2, ab[]={10,20}, c;   printf( "%d", M(a,b)[a] );   printf( "%d", M(a,b)[a]?a:b );   printf( "%d", c=M(a,b)[a]?a:b ); } 

So, keep in mind that a##b will merge together the input into a single identifier. Since the macro is just passed a and b, the result is just ab, so you effectively have:

main() {   int a=1, b=2, ab[]={10,20}, c;   printf( "%d", ab[a] );   printf( "%d", ab[a]?a:b );   printf( "%d", c=ab[a]?a:b ); } 

The assignment to c is not really relevant, so we can get rid of that:

main() {   int a=1, b=2, ab[]={10,20};   printf( "%d", ab[a] );   printf( "%d", ab[a]?a:b );   printf( "%d", ab[a]?a:b ); } 

Now, let's get rid of the ternary operator (?:), because we can work it out statically (ab[a] is always true because a is 1 and ab[1] is 20, i.e. non-zero):

main() {   int a=1, b=2, ab[]={10,20};   printf( "%d", ab[a] );   printf( "%d", a );   printf( "%d", a ); } 

Now, replace variables with their actual values, i.e. ab[a] with 20 and a with 1

main() {   int a=1, b=2, ab[]={10,20};   printf( "%d", 20 );   printf( "%d", 1 );   printf( "%d", 1 ); } 
like image 173
dreamlax Avatar answered Dec 26 '22 15:12

dreamlax