3

Can someone explain to me why the value of y here is 13?

#include <stdio.h>
#define avg_sum(n) n * (n-1)/2
int main(){
    int y;
    int z = 9;
    y = avg_sum(z+1);
    printf("y=%i\n",y);
}
1
  • 2
    That's why you always use parentheses around macro arguments when they are part of an arithmetic expression, and parentheses around the macro body as a whole, too, so that 934 / avg_sum(12) gives you the expected answer too. Commented Dec 10, 2013 at 21:00

3 Answers 3

9
avg_sum(9+1) 9+1 * (9+1-1)/2 = 9 + 9/2 = 9+ 4 = 13

macros expand each time so 9+1 is not the same as 10, it might be better with safeguarding parenthesis as follows:

#define avg_sum(n) ((n) * ((n)-1)/2)

but an equivelant function will do you much better and be more intuitive and will evaluate arguments only once

avg_sum(a++) will be ((a++) * ((a++)-1)/2) and will increment a twice whereas a function will not have these issues since all arguments are evaulated before the function is called

Sign up to request clarification or add additional context in comments.

4 Comments

static inline int avg_sum(int n) { return (n * (n-1)) / 2; } works nicely, unless you're stuck with an archaic C90 compiler (eg the default on Windows, MSVC).
@JonathanLeffler in the function version, I'm not sure you need all the parens
I was not sure either, but better safe than sorry. Thinking about how things can go wrong if (n-1)/2 is evaluated before it is multiplied by n: suppose n == 4. Then (n-1)/2 is 1 and n*1 is 4; OTOH, (4 * 3)/2 is 6. I think the parentheses do matter, if the compiler is allowed to reorder operations, and I think it is.
@JonathanLeffler 5 | * / % | Multiplication, division, and remainder | left to right No reordering allowed - no parens needed
5

The best way to answer these sorts of questions is to simply expand the macro in question:

y = avg_sum(z+1);

y = z + 1 * (z + 1 - 1) / 2

y = 9 + 1 * (9 + 1 - 1) / 2

y == 13

This is why you add parentheses around your macro arguments.

#define avg_sum(n) ((n) * ((n)-1)/2)

Comments

2
y = avg_sum(z+1);

expands to z + 1 * (z+1-1)/2 but it's wrong. Change your macro to

#define avg_sum(n) ((n) * ((n)-1)/2)

And always parenthesize as well arguments of functional macros as the macro itself . It's an important rule.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.