This question already has answers here:
Problem with Macros
(4 answers)
Closed 9 years ago.
On the snipet below, the operator ++ is called two times.
Why ??
#define CALL_WITH_MAX(a,b) ((a) > (b) ? (a) : (b))
int main()
{
int a = 5, b =0;
CALL_WITH_MAX(++a,b);
// a was incremented by one two times !!!!
CALL_WITH_MAX(++a,b+10);
//a incremented as expected...
return 0;
}
CALL_WITH_MAX(++a,b)
expands to
((++a) > (b) ? (++a) : (b))
^ ^ //A is incremented twice when ++a < b
++a = 6 and b = 0
6 > 0 == true
++a is returned => ++a = 7
In your second option
++a = 6 and b = 0 + 10 = 10
6 > 10 == false.
This time just b is returned.
Because argument is taken as is - without extracting variable names, etc. That's what it becomes:
((++a) > (b) ? (++a) : (b));
As incremented a is greater than b, the second part of ternary expression will be evaluated as well.
In the second case, however, the clause is falsy: 6 is less than 10. That's why third part of the ternary is evaluated instead, and a will be incremented just once.
If the first argument is larger than the second, it is evaluated 2 times.
Therefore in the first case you have:
(++a) > (b) ? (++a) : (b)
and since (++a) > (b) you get (++a), which increments a once more.
If you expand the macro it will become like
((++a) > (b) ? (++a) : (b))
6 > 0 then a is again incremented.
The macro expands to:
((++a) > (b) ? (++a) : (b))
vs.
((++a) > (b+10) ? (++a) : (b+10))
in the former, ++a is evaluated twice
The macro is not "compiled", it's completely different from writing a function you run during the execution of your application. Treat a macro as something that helps you write your code, not perform calculations.
Therefore
CALL_WITH_MAX(++a,b)
will generate
((++a) > (b) ? (++a) : (b));
which then is "read" by the compiler and compiled to actual code. This means that a will be incremented twice, because b is smaller than a, and therefore the (++a) is run. If b is larger, then the second (++a) is not executed and only b is returned.
This is why macros are also known as preprocessor directives, because they are used in the preprocessing phase of the build process. The values of the variables are not read or changed, the directive just reads the text you provide it with and generates code for you.
If you look at macros that already exist like __LINE__, it will return the line number for you in your code; however it will literally insert it as part of your code, it will not be a function that is run during the execution of your application. Similarly the macro __TIME__ will not return the current time but the time of when the compilation process was started.
I hope this will help you to change your approach to macros and how they work.
Most of the answers on this questions are correct. Here is a typical fix for the issue:
#define CALL_WITH_MAX(a,b) ({ typeof(a) _a=a; typeof(b) _b=b; ((_a) > (_b) ? (_a) : (_b)); })
Works with gcc.
Basically, it creates a copy of a & b, with same data types & operates on these copies.
The only time a gets incremented is at _a=a; statement in macro.
You can test the expansion with -E flag to gcc; like gcc -E test_macro.c ...
The prefixed increment operator has higher order of procedure so the value of the variable is increased by 1 before evaluation .
you call your function with arguments (++a,b) so you need to replace all the variable with this passed value so the function can be expressed as
`CALL_WITH_MAX(a,b) ((a) > (b) ? (a) : (b))
CALL_WITH_MAX(++a,b); `
so if you replace all a by ++a and b and b then your function can be expressed as
((++a) > (b) ? (++a) : (b))
the value of a is incremented by 1 before evaluation ..
I noticed in your code, you chose to name the macro's parameters a and b, which is also the name you used for your variables within your main function.
In my opinion, the problem you're having here is you probably think by naming them the same that they're linked somehow.. which is simply not true.
The parameters names in the macro don't tie them to variables of the same name in the program, they’re replaced by what you pass in. You might find this easier to see if we change the names a bit:
#define CALL_WITH_MAX(x,y) ((x) > (y) ? (x) : (y))
Then in your main program:
int a = 5, b =0;
CALL_WITH_MAX(++a,b);
Now you can see that x is replaced with ++a and y will be replaced by b. So the logic of your macro becomes:
if x > y then return x else return y
if ++a > b then return ++a else return b
if 6 > 0 then return 7 else return 0
So obviously 6 is greater than 0, so you increment again and return the value.
// a = 7; b = 0
CALL_WITH_MAX(++a,b+10);
So again, the same logic:
if x > y then return x else return y
if ++a > b then return ++a else return b
if 8 > 10 then return 9 else return 10
In this case 8 is not greater than 10, so we don't increment to 9, we just return 10. Thus after the first call to your macro a was incremented twice and after the second call a was only incremented once; hope that made it clearer.
Related
#define SQUARE(x,y) (x<y?x:y)
int a = 5, b = 6, c = 3;
int var = SQUARE(a & c,b);
I have searched and learnt that '<' precede '&'. As per rules it should give '5'. But it is giving output as '1'. But in some cases it is giving right output. Can you please explain macro rules of this and what am I missing here.
Macros are just replaced by the preprocessor, so the arguments are not evaluated and then passed like in functions.
In your example the expression SQUARE(a & c, b); will become (a & c < b ? a & c : b);
For a=5, b=6, c=3 it evaluates to:
(5 & 3<6 ? 5&3 : 6) //'<' precede '&' as you correctly mentioned
(5&1 ? 5&3 : 6) // '3 < 6' is a boolean expression which evaluates to 1. '&' is bitwise AND.
(1 ? 1 : 6)
(1)
So 1 is the right output.
EDIT:
A good aproach is to always use parentheses around your arguments and the whole expression to eliminate the problem of operator precedence.
As mention by others it can be dangerous to use macros due to multiple evaluation, which may not only effect performance.
For example:
#define SQUARE(x) ((x)*(x))
seems to only square the argument, but if you call it like
f = SQUARE(x++);
you will get undefined behaviour. A better approach for small function would be to declare it as inline.
inline int square(int x)
{
return x*x;
}
Also as mentioned by #EricPostpischil macros are not a textual replacement as the preprocessor replaces by tokens.
For example:
#define a 1
#define b 2
printf("%d\n", ab);
here ab is not replaced with 12 as someone would expect for pure textual replacement.
Macros require parentheses as they are not functions and just do the textual replacement
#define SQUARE(x,y) (((x)<(y))?(x):(y))
The macro is extremely side effects error and UB prone:
Example: SQUATE(x++,y)
in your example 5 & 3 will be evaluated every time you have the x in your macro. It will be less effective than the inline function
inline unsigned SQUARE(unsigned x, unsigned y)
{
return (x < y) ? x : y;
}
In a bit more detail, as #P__J__ said, macros are just text replacement by the pre-processor, not functions. So this:
#define SQUARE(x,y) (x<y?x:y)
int a = 5, b = 6, c = 3;
int var = SQUARE(a & c,b);
is translated to:
int a = 5, b = 6, c = 3;
int var = (a & c<b?a & c:b);
Because every x is replaced with a & c and every y is replaced with b.
If you also apply the values as in #Osiris 's answer, you'll get:
int var = (5 & 3 < 6 ? 5 & 3 : 6);
At this point, as you already said, < takes precedence over &.
The result of < is true or false, which means 1 or 0, so 3 < 6 becomes 1.
The result of & is the bitwise AND between two numbers, which in this case is also 1 (because 5 is 101 and 3 is 011).
This is why it becomes
(5 & 1 ? 1 : 6)
That next 5 & 1 will also become 1 (because of the AND between 101 and 001), so you'll get:
(1 ? 1 : 6)
And since 1 is true, you'll get the first value, which is also a 1.
Also, as already pointed out, be careful with evaluation in a macro.
These are just numbers and you're already seeing some not so obvious behaviour, but if had passed a function as one of the arguments, that function would've run multiple times.
For example
#define SQUARE(x,y) (x<y?x:y)
int var = SQUARE(update_counter(a), 1);
would have been translated to
int var = (update_counter(a) < 1 ? update_counter(a) : 1);
Thus potentially updating a hypothetical counter twice.
#include <stdio.h>
#define max(x,y)(x)>(y)?x:y
int main() {
int i = 10;
int j = 5;
int k = 0;
k == max(i++, ++j);
printf("%d%d%d ", i, j, k);
return 0;
}
I know the answer. It is 11 7 0 but how? please help me with the execution of the ternary operator.
The statement
k==max(i++,++j);
is expanded to
k==(i++)>(j++)?i++:j++;
Note that == has higher precedence than ?: operator and therefore the above expression is equivalent to
( k == ((i++)>(j++)) )?i++:j++;
Since (i++)>(j++) will be true, therefore k == ((i++)>(j++)) is evaluated as false and hence j++ (and it's value become 7) will be evaluated (i++ will be skipped).
NOTE: The above expression does not invoke undefined behavior because there exists sequence point between the evaluation of the first operand of the ternary operator and the second or third operand. For example, the expression
a = (*p++) ? (*p++) : 0
has well defined behavior.
This question is definitely a trick question that will catch many unsuspecting C programmers. The different responders here have more than 100 years of compounded experience in C, yet it took several tries to get this right:
The expression k == max(i++, ++j); expands to:
k == (i++)>(++j)?i++:++j;
Which is parsed as this (== has lower precedence than >, but higher precedence than ?):
(k == ((i++) > (++j)))
? i++
: ++j;
The ternary operator evaluates the test (i++)>(++j), which is true for the values in the program, hence evaluates to 1, different from the value of k, so it proceeds to evaluate the third expression j++, which increments j a second time and returns the intermediary value 6. There is a sequence point between the test and the branch that is executed, so it is OK to increment j twice. The second branch is not executed at all since the test evaluated to false.
i is incremented once, its value becomes 11.
j is incremented twice, its value is 7.
k is not modified by the above statement, because == is the comparison operator, not the assignment operator.
Hence the output is 11 7 0
Notes:
The program uses a macro max that evaluates its arguments more than once and they are not properly parenthesized in the expansion: 2 errors that illustrate the shortcomings of macros. This macro should be names MAX to emphasize the fact that its arguments should not have side effects and its expansion should be fully parenthesized this way:
#define MAX(x,y) ((x) > (y) ? (x) : (y))
A better alternative is to make it an inline function:
static inline int max(int x, int y) {
return x > y ? x : y;
}
If the program had this statement:
k = max(i++, ++j);
The output would be 12 6 11 because unlike ==, = has lower precedence than ? so the statement would expand to:
k = ((i++) > (++j))
? i++
: ++j;
You can study the table of operator precedence for C. There are in my humble opinion too many levels and it is very difficult to memorize all of them, especially since some of them are rather counter-intuitive: print a copy and keep it handy or make a bookmark. When in doubt, use parentheses.
You're using a double equal sign, which is a comparison. k==max(i++,++j); compares the return value of max to k, which is 0.
Instead, try changing the == to =.
This question already has answers here:
Why is "i" variable getting incremented twice in my program?
(8 answers)
Closed 6 years ago.
In the code below, according to me, the output should be 11 6 10, but it gives 12 6 11. The value of k=x as returned by the ternary operator since x>y where x=10 and y=6, so i=11, j=6 and k=10, so why is there a mismatch in the output produced?
#include <stdio.h>
#define MAX(x,y)(x)>(y)?(x):(y)
int main()
{
int i=10,j=5,k=0;
k=MAX(i++,++j);
printf("%d %d %d",i,j,k);
return 0;
}
The expansion is equivalent to:
k = (i++) > (++j) ? (i++) : (++j);
Both i and j are incremented as the condition is evaluated (so i becomes 11 and j becomes 6. Since the condition checks the original value of i and the incremented value of j and 10 > 6, the i++ after the ? is evaluated, so k is assigned 11 and i is incremented to 12.
Hence the output is, as it should be:
12 6 11
There is no undefined behaviour here. There's a full sequence point after the condition is evaluated.
Note, too, that for full safety, the macro should have an extra set of parentheses around the expansion:
#define MAX(x,y) ((x) > (y) ? (x) : (y))
Otherwise, you get odd-ball effects from:
int l = 7 * MAX(k, i) + 3;
It works; it just doesn't work as expected.
The output works as expected. You'll need to understand macros are expanded, and do not work like functions where the input parameters are copied.
The definition of MAX in the above code is
#define MAX(x, y) (x)>(y)?(x):(y)
So
k = MAX(i++, ++j)
expands to
k = (i++)>(++j)?(i++):(++j)
The variable i gets incremented twice when i=10 and j=5. The variable j gets incremented only once.
So eventually i=12 and j=6, and k=11 because the second operand in the ternary operator is a post-increment.
If you are using gcc, running cpp instead of gcc on the .c file would expand the macro nicely for you.
Apart from Jonathan Leffler's comment on using more parentheses in the macro for safety, you can consider using inline functions that could save you from these unintended results. Inline functions have the benefits of being typed, passing-by-value, and code expansion.
inline int max(int x, int y) { return x > y ? x : y; }
See the wiki for more details.
I came across a statement in the text C How to Program:
"Expressions with side effects (i.e., variable values are modified) should not be passed to a macro because macro arguments may be evaluated more than once.".
My question is what are expressions with side effects and why should they be not passed to a macro?
The classic example is a macro to calculate the maximum of two value:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
Now lets "call" the macro like this:
int x = 5;
int y = 7;
int z = MAX(x++, y++);
Now if MAX was a normal function, we would expect that x and y would be incremented once, right? However because it's a macro the "call" is replaced like this:
int z = ((x++) > (y++) ? (x++) : (y++));
As you see, the variable y will be incremented twice, once in the condition and once as the end-result of the ternary operator.
This is the result of an expression with side-effects (the post-increment expression) and a macro expansion.
On a related note, there are also other dangers with macros. For example lets take this simple macro:
#define MUL_BY_TWO(x) (x * 2)
Looks simple right? But now what if we use it like this:
int result = MUL_BY_TWO(a + b);
That will expand like
int result = (a + b * 2);
And as you hopefully knows multiplication have higher precedence than addition, so the expression a + b * 2 is equivalent to a + (b * 2), probably not what was intended by the macro writer. That is why arguments to macros should be put inside their own parentheses:
#define MUL_BY_TWO(x) ((x) * 2)
Then the expansion will be
int result = ((a + b) * 2);
which is probably correct.
To put it simply a side effect is a write to an object or a read of a volatile object.
So an example of a side effect:
i++;
Here is a use of a side effect in a macro:
#define MAX(a, b) ((a) > (b)) ? (a) : (b))
int a = 42;
int b = 1;
int c;
c = MAX(a, b++);
The danger is contrary to a function where the arguments are passed by value you are potentially modifying b object one or two times (depending on the macro arguments, here one time) in the macro because of the way macros work (by replacing the b++ tokens in the macro definition).
Side Effects can be defined as:
Evaluation of an expression produces something and if in addition there is a change in the state of the execution environment it is said that the expression (its evaluation) has some side effect(s).
For example:
int x = y++; //where y is also an int
In addition to the initialization operation the value of y gets changed due to the side effect of ++ operator.
Now consider a macro for squaring of an integers :
#define Sq(a) a*a
main()
{
int a=6;
int res=Sq(a);
printf("%d\n",res);
res=Sq(++a);
printf("%d",res);
}
You would expect the output to be
36
49
However the output is
36
64
because macro results in textual replacement and
res becomes (++a)*(++a)
i.e, 8*8=64
Therefore we should not pass arguments with side effects to macros.
(http://ideone.com/mMPQLP)
I'm looking at something like this:
#define foo(x) \
(((a > b) ? \
0 : 1), \
(c ? 2 : 3), \
(d ? 4 : 5))
I'm not sure how to interpret this. Can someone help me out?
Essentially the \ ignores the newline as far as terminating the #define statement is concerned, so each time you write foo(var) in your code it will be replaced with
((((a > b) ?
0 : 1),
(c ? 2 : 3),
(d ? 4 : 5))
The comma operator doesn't do a whole lot, except the final "returned" value of a statement consisting of statements separated by comma operators is the right most value.
All of that being explained, this isn't really a terribly valid #define since you use a,b,c, and d in the #define and only reference x as a parameter
The comma operator evaluates all of its operands and returns the value of the last one. So, a, b, c and d will be evaluated and the result of f(x) will be either 4 or 5, depending on whether d is non-zero.