4

I'm new to dealing with Macros and I've just stumbled into an exercise that I can't figure it out. Could someone explain to me what's happening here? If I compile i can see what the output is but i can't get it there myself. Thank you in advance!

#define M(varname, index) ( ( (unsigned char*) & varname )[index] ) 

int main(void) {
int a = 0x12345678; 
printf( "%x %x\n", M(a,0), M(a,3) );
printf( "%x %x\n", M(a,1), M(a,2) );
}
kasedaime
  • 49
  • 2
  • 1
    It is text substitution: replace the arguments where they occur in the macro definition, with the parameters passed. – Weather Vane Jun 25 '16 at 14:50
  • 4
    Feed the program through the pre-processor `cpp` to see what the replacement is. After that, it's pointer arithmetic ... – Thomas B Preusser Jun 25 '16 at 14:50
  • I can explain "what's happening here" but to get better answer can you please tell us what you expected to see as output and what you actually see? – mvidelgauz Jun 25 '16 at 14:51

2 Answers2

6

Each Macro usage M(x,y) is replaced with ( (unsigned char*) & x )[y]

So your code looks like this after preprocessing:

int main(void) {
    int a = 0x12345678; 
    printf( "%x %x\n", ( (unsigned char*) & a )[0], ( (unsigned char*) & a )[3] );
    printf( "%x %x\n", ( (unsigned char*) & a )[1], ( (unsigned char*) & a )[2] );
}

Like Thomas B Preusser added in the OP Question comments, most C compiler suites allow to get the pre-processed code with certain compiler flags or tools like f.e. with GCC as mentioned here.

Community
  • 1
  • 1
makadev
  • 1,034
  • 15
  • 26
3

Macros work by replacing one thing with another before attempting to compile the code (preprocessing). So in the example you gave:

#define M(varname, index) ( ( (unsigned char*) & varname )[index] ) 

Each time a M(varname, index) occurs, it will be replaced by ( (unsigned char*) & varname )[index]

In terms of what the code is doing, as an example (reformatted slightly for readability):

printf("%x %x\n", ((unsigned char*) &a)[0], ((unsigned char*) &a)[3]);

This:

  • takes the address of variable a
  • casts the address to an unsigned char*
  • gets the 0th element in this pointer/array
  • formats it into the string, replacing the first %x, as hex (%x is for hex)

It repeats this for the 3rd element with the second %x

G. May
  • 66
  • 1
  • 4