1

I have this code inside a function but I am not able to understand what it does.

....
#define ascend(i) do {\
            int h = nodes[i].heavyindex;\
            int p = nodes[i].heavypos;\
            m##i = max(m##i + paths[h].ftree.sum(p), paths[h].stree.max_(0, p));\
            i = paths[h].parent;\
        } while (0)
    while (nodes[a].heavyindex != nodes[b].heavyindex) {
        if (nodes[a].heavyindex > nodes[b].heavyindex) {
            ascend(a);
        } else {
            ascend(b);
        }
    }
#undef ascend
...

The code of #define, I think, is:

#define ascend(i) do {\
            int h = nodes[i].heavyindex;\
            int p = nodes[i].heavypos;\
            m##i = max(m##i + paths[h].ftree.sum(p), paths[h].stree.max_(0, p));\
            i = paths[h].parent;\
        } while (0)

so the real code inside the function is only this:

while (nodes[a].heavyindex != nodes[b].heavyindex) {
        if (nodes[a].heavyindex > nodes[b].heavyindex) {
            ascend(a);
        } else {
            ascend(b);
        }
    }

1) It is right?
2) I want to move the code of the #define inside a function to better understand what it does, but how I translate the following line?

m##i = max(m##i + paths[h].ftree.sum(p), paths[h].stree.max_(0, p));\ 
user72708
  • 1,235
  • 3
  • 13
  • 20
  • 1
    `m##i` is using the token-pasting operator, it will become either `ma` or `mb`. You'll need to pass the function a pointer (or in C++, a reference) to it, in order to read and write it from inside the function. – Ben Voigt Mar 20 '15 at 00:10
  • 1
    Most compilers can output the preprocessed source code. For Gcc, it's `gcc -E`. – mafso Mar 20 '15 at 00:16
  • What's the type of `ma` and `mb`? – Emil Laine Mar 20 '15 at 00:19
  • Regardomg the `do{} while(0)` construct, read here http://stackoverflow.com/questions/154136/do-while-and-if-else-statements-in-c-c-macros – leonbloy Mar 20 '15 at 00:24
  • [zenith](http://stackoverflow.com/users/3425536/zenith) `ma` and `mb` are int – user72708 Mar 20 '15 at 11:45

1 Answers1

1
  1. Yes.
  2. As mentioned by Ben Voigt in the comments, ## is the token-pasting operator. So with #define f(i) m##i defined, f(a) will expand to ma, f(b) will expand to mb, etc.

    Since that's only possible with the preprocessor, you have to think of something else to implement it as a function. Passing ma and mb by reference would be a good idea. It could look something like this:

    ascend(T& mi) {
        ...
        mi = max(mi + paths[h].ftree.sum(p), paths[h].stree.max_(0, p)); 
        ...
    }
    

    Where T is the type of ma and mb. If they're of different types, you need to make it a function template.

Community
  • 1
  • 1
Emil Laine
  • 41,598
  • 9
  • 101
  • 157
  • It's important to note that this is a C++ answer. If OP is really looking for a C answer, this will need some (minor) semantic cleanup, and a function template is not possible. – Degustaf Mar 20 '15 at 00:40