Does macro function with operator precedence show unusual result? - c

#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.

Related

How does macro expansion work in below code? [duplicate]

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.

What are expressions with side effects and why should they be not passed to a macro?

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)

Why do I get different results when using a function versus a macro?

I'm using DevCPP IDE and I found that while programming in c,
Value returned by:
float f(float x)
{
return 1/(1+x*x);
}
and value returned by f(x) if it's defined as:
#define f(x) 1/(1+x*x)
are different.
Why am I getting different results in these cases?
EDIT:
Here's my code for which I'm getting the anomaly:
main()
{
int i;
float a=0, b=1, h, n=12, s1, s2=0;
h=(b-a)/n; //step length
s1=f(a)+f(b);
for(i=1;i<=n-1;i++)
{
s2+=f(a+(i*h));
}
s1=(s1+2*s2)*h/2;
printf("sum: %f", s1);
getch();
}
OUTPUT 1: 0.693581 (using MACRO)
OUTPUT 2: 0.785109 (using function)
There are many possibilities here. Here's a few.
In the function version, the argument is explicitly typed as a float. This means that if you call
f(1);
then 1 is converted to the float 1.0f as the argument. Then, when 1 / (1 + x * x) is computed, it evaluates to 1 / 2.0f, which comes out to 0.5f. However, in the macro version, f(1) would be evaluated as 1 / 2 using integer division, yielding the value 0.
Second, in the function version, the argument is evaluated only once. This means that
int x = 0;
f(x++);
will increment x to 1, then pass in the value 0. The result will then be 1.0f. In the macro version, however, the code expands to
1 / (1 + x++ * x++)
This causes has undefined behavior because there is no sequence point between the evaluations of x++. This expression could evaluate to anything, or it could crash the program outright.
Finally, the function version respects operator precedence while the macro does not. For example, in the function version, calling
f(1 - 1)
will call f(0), evaluating to 1.0f. In the macro version, this expands to
1 / (1 + 1 - 1 * 1 - 1)
= 1 / (1 + 1 - 1 - 1)
= 1 / 0
This causes undefined behavior because of a divide-by-zero error.
The simple way to avoid this is to not use macros to define functions. Way back in the Bad Old Days this was a standard practice, but now that C has inline functions and compilers are way smarter, you should prefer functions to macros. They're safer, easier to use, and harder to mess up. They're also type aware and don't evaluate arguments multiple times.
Hope this helps!
#define f(x) 1/(1+x*x)
should be defined as
#define f(x) 1/(1+(x)*(x))
Try this:
#define f(x) (1/(1+x*x))
A #define basically sticks the code where the #define'd name was, so order of operations and precedence will apply.

C Macro Behavior

I have the simple following C code
#define Sqrt(A) A * A
int main(void) {
int A = 10;
int x = Sqrt(A+1);
return 0;
}
For some reason, when I used it like that, with A+1, I get x to be 21, which is probably 10+11.
My question is, how is the multiplication is being ignored?
If I switch the macro with the macro text, I get the right result which is 121.
Thanks.
First, your Sqrt is misnamed, should be Square (not square root)
Then, generate the preprocessed form (i.e. with gcc -C -E) and look inside it.
#define Sqr(A) A * A
int a = 10;
int x = Sqr(a+1);
where the last line is expanded as
int x = a+1 * a+1;
Which is parsed as
int x = a+(1*a)+1;
Moral of the story, always use extra parenthesis in macro definition, i.e.
#define Sqr(A) ((A)*(A))
Even with such a definition, Sqr(a++) is probably undefined behavior and at least is naughty.
So you want to avoid macros and actually, learn to use inline functions like
inline int square(int a) { return a*a; };
BTW, you will want to make it static inline not just inline (and put that in a header file)
'cos
#define Sqrt(A) A * A
makes
Sqrt(A+1);
translate to
A + 1 * A + 1
and A is 10
so you get
10 + 1 * 10 + 1
Now do the maths!
BTW sqrt has seems to say square root not squared!
You define the macro as A * A. So, Sqrt(A + 1) expands to A + 1 * A + 1, which is, due to operator precedence, equal to 2 * A + 1 - you've got 2 * 10 + 1 = 21.
That's why you should always parenthesize your macros and their arguments:
#define Sqrt(A) ((A) * (A))
By the way, why a macro? What if one day you write Sqrt(A++)? Then you can expect nasal demons. It would be safer to write an inline function instead (horribile dictu, a correctly named inline function):
static inline double square(double x)
{
return x * x;
}
Inside the macro, A is replaced with whatever was passed into the macro invocation. In this case, that is A+1. This means that the macro gets expanded to:
A+1 * A+1
Due to operator precedence, this is interpreted as A + 1*A + 1, or 10 + 10 + 1 = 21.
You should define the macro as #define Sqrt(A) ((A) * (A))
BODMAS rule buddy!! as the previous answers suggests. Multiplication takes place before your addition.
Your opertaion Sqrt(A+1) where A = 10 will evaulate to 10+1*10+1
10+10+1
21!!
Macros are substituted literally and then evaluated.
Since multiplication has more priority than addition, when you give A+1 to the macro it becomes 10 + 1 * 10 + 1 => 10 + 10 + 1 => 21
Likewise if you give A+2 ..... 10 + 2 * 10 + 2 => 10 + 20 + 2 => 32.
when you call x = MACRO_NAME(A+1); this statement is replace as x = A + 1 * A + 1
in c priority of multiplication is more than addition so it will be 1st executed 1*A which give as A, then A+A+1 will give you result as 21`enter code here`
i.e A+1*A+1
= A+A+1
= 21
for proper answer you need to write Macro as #define MACRO_NAME(A) (A) * (A) which give you result as
121

C multiple operations in single row

I would like to do this in one line (C programming language):
int x = index >> 8;
int y = x < 10 ? x+1 : x+2;
Is it possible? How do I reference to value before ? sign, if I don't have it stored in separate integer?
"int y = (index >> 8) < 10 ? [what]+1 : [what]+2;"
You simply need to repeat the expression:
int y = (index >> 8) < 10 ? (index >> 8) + 1 : (index >> 8) + 2;
It's not very nice, or readable, so I don't get why you must do it this way. There's no built-in way in the language to reference the expression before the ?. Since expressions can have side-effects in C, it would be quite hairy if there was.
The way you have this expression is the best you can get there without code repetition.
If you absolutely need it to be a single string, you can simply do the following:
int y = (index >> 8) < 10 ? (index >> 8)+1 : (index >> 8)+2;
Because C makes no distinction between whitespace characters, you can have it in a single line:
int x = index >> 8; int y = x < 10 ? x+1 : x+2;
...which is completely valid C.
However your y and x values are not inter-dependent, so you can simplify the expression to just y:
int y = index >> 8; y = y < 10 ? y+1 : y+2;
If your y already exists, you can make use of the little-used comma operator to eliminate the semi-colon and reduce it to a single statement:
y = ( y = index >> 8 ), y < 10 ? y+1 : y+2;
Note that you cannot use the comma operator inside a value declaration statement because in that context it becomes the sequence separator.
It is generally not useful to try to optimize source code in this way. C does not specify what specific operations the computer must perform; C specifies what results a program must achieve. (By means of the “as if” model in C. The program the compiler produces must produce results as if you stepped through the specific operations you wrote, but those results can actually be obtained by any sequence of instructions the implementation chooses. The program only needs to reproduce results, not mechanisms.)
Generally, you should write your code to be clear, and you should allow the optimizer in the compiler to do its job of performing the calculations efficiently.
It is possible using this form :
int y = (y = index >> 8) < 10 ? y+1 : y+2;
Here, y get assigned the temporary value of index >> 8, so you can reuse that value after the ? operator.
And contrary to David's similar answer, this form work inside a value declaration statement as well.
Alternatively, by removing the ternary. The shift being equivalent to a division by 256, we can compare the value also before the shifting.
int y = (index >> 8) + 1 + (index >= 2560);
Of course, index should be positive for this to work.
EDIT: the expression has also the advantage of having no temporary write access and no sequence point.

Resources