Let's assume we have the following code in a language that looks a lot like C.
int A[2];
A[0]=4;
A[1]=7;
void f(int x, int y) {
x++; A[1]++; y++;
printf(x, y, A[0], A[1]);
}
void main() {
int k = 0;
f(k, A[k]);
print(k, A[0], A[1]);
}
I want to define the output of this program. I haven't understood well the difference between the call-by-name and the call-by-macro-expansion method.
So, in the call-by-name method, k is initialized to 0 and then f() function is called. x becomes equal to "k" and y becomes equal to "A[k]". The first command in the called function is x++ which increases the value of "k" by 1. So k becomes equal to 1. Then A[1] is increased, so A[1] becomes 7+1=8. None of the x,y are affected. Finally, we have the command y++ which increases the value of "A[k]" by 1, so it increases the value of A[1] (since now k=1) by 1, so A[1] becomes now 8+1=9.
Then f() prints: 1,9,4,9
And then we return to the main() fuction which prints: 1,4,9
So, the output of the program is 1,9,4,9,1,4,9 if I am not mistaken.
But how does call-by-macro-expansion differs from this method? What does it change?
For C, "call-by-macro-expansion" doesn't exist. Instead, for macros the preprocessor does a glorified "cut&paste" operation on raw text.
For example, if you have this:
Then the preprocessor will cut&paste the text from the macro to where the macro is used and then replace
xandywith the arguments you provided, so that (after preprocessing) the source code looks like this:Of course the macros don't need to contain valid code, and the source doesn't even need to be C at all (e.g. you could use the preprocessor to preprocess assembly language source code by telling the compiler "don't compile, just output the preprocessed text"); and there's no real reason why you can't use a completely different preprocessor (with completely different features and/or macro syntax) and feed the resulting text into a C compiler (telling the compiler "don't preprocesses, just compile").
In practice; the main differences for macros and functions are:
#define forever while(1) {so you can useforever i++; }as an infinite loop), and can be powerful for code obfuscation (deliberately making it hard to read the code).For a simpler example of (a) difference, consider this code:
These look the same, but are not. After expanding the macro and inlining the function, it becomes more like this:
Note that this is exactly the same problem with the example above (for the macro, the
x++;modifies the originalkand not a copy of the originalk; and for the function thex++;modifies a copy and not the original).