0

I am learning C programming. And this was a question I faced very recently in an examination.

Can someone tell me why the output of the following program doesn't adhere to my reasoning(which I have explained in a concise and lucid manner below).

#include<stdio.h>
#define PRODUCT(x) ( x * x ) 
main( ) 
{ 
int i = 3, j, k ; 
j = PRODUCT( i++ ) ; 
k = PRODUCT ( ++i ) ; 
printf ( "\n%d %d", j, k ) ; 
}

Expected Output: 12 42 The Real Output: 12 49 .

My Reasoning for 'The Expected Output':

The PRODUCT (i++) gets replaced with the following: ( i++ * i++) which (since "i++" is a posterior operator) essentially is mathematically equivalent to ((i)*(i+1)) . And so j = 3 * 4.

At the end of this assignment to j, the value of 'i' is 5. Since in (i++ * i++) the first i++ incremented i once and then again for the next i++ after the '*' symbol. Hope you are with me. So after two increments, i now equals 5. Lets move further.

In the assignment statement for k, the PRODUCT (++i) gets replaced with (++i * ++i) which being a pre-increment operator is the mathematical equivalent of ( (i+1) * ((i+1)+1 ) ). And since i equals 5 until before this statement, the value assigned to variable 'k' should be ((5+1)((5+1)+1)) which is (67)=42 AND NOT "49"-which is the output I got. Any reasoning other than undefined behavior will be much appreciated.

Krishan
  • 11
  • 3
  • 4
    _"The PRODUCT (i++) gets replaced with the following: ( i * (i+1))"_: no, `PRODUCT (i++) ` will be replaced with `i++ * i++` which is undefined behaviour. – Jabberwocky Dec 04 '20 at 13:00
  • The behavior is undefined. Whoever wrote this question should refresh their C knowledge. – interjay Dec 04 '20 at 13:00
  • @Jabberwocky Please explain, how it is an undefined behaviour. AFAIK, it will be `3 * 4` and then `i = 5` – Shubham Dec 04 '20 at 13:04
  • @Lucas read the [duplicate](https://stackoverflow.com/questions/949433/why-are-these-constructs-using-pre-and-post-increment-undefined-behavior) – Jabberwocky Dec 04 '20 at 13:04
  • The duplicate is kind of fragmented and generally bad, I'd recommend the more detailed and complete [Why can't we mix increment operators like i++ with other operators?](https://software.codidact.com/q/278384) instead. (But then I'm partial, naturally.) – Lundin Dec 04 '20 at 13:21
  • @Lucas The problem with `i++ * i++` is that you are telling the compiler "you may go buy a cake before or after the point where you may eat your cake and still have it". There's simply no telling how many cakes you have after that, because everything is based on senseless premises. – Lundin Dec 04 '20 at 13:40
  • 1
    As a new C programmer, the comp.lang.c FAQ is required reading: http://c-faq.com/expr/index.html Q 3.2 gets near your problem, but all of section 3 on expressions is valuable. – Jens Dec 04 '20 at 14:15
  • Can anyone clearly tell me why I got that output? Please – Krishan Dec 07 '20 at 04:50
  • You should ask for your money back, if you paid any. – Tanveer Badar Jan 06 '21 at 13:44
  • Read documentation of [GCC](http://gcc.gnu.org/) and of [GNU cpp](https://gcc.gnu.org/onlinedocs/cpp/). Then read the [n2176](https://files.lhmouse.com/standards/ISO%20C%20N2176.pdf) draft standard – Basile Starynkevitch Jan 06 '21 at 13:45
  • It looks like **in this particular case** that the side effect of `i` being incremented is applied in both cases before the rest of the expression is evaluated. However because this is UB that result cannot be depended on. Other compilers may evaluate it differently. For example, with gcc 4.8.5 I get "12 49" but with MSVC 2015 I get "9 49". – dbush Jan 06 '21 at 13:53
  • 1
    @Lucas: It's undefined because you have two side effects on the same object that are *unsequenced* relative to each other (arithmetic expressions are not guaranteed to be evaluated left to right, right to left, or in any other order, and those evaluations can even be interleaved). Additionally, the side effect does not have to be applied immediately after evaluation, only before the next sequence point (in this case, the end of the statement). The result *will* vary based on the underlying platform, compiler, even the surrounding code. – John Bode Jan 06 '21 at 17:49
  • @JohnBode Thanks for your valuable comment. I got understood, what you explained. – Shubham Jan 07 '21 at 14:57
  • Use parenthesis around the argument in your macro : `PRODUCT(x+1) ` would be compiled as `x+1*x+1` = `x + (1 * x) + 1`. So write `#define PRODUCT(x+1) ((x)*(x))`. – limserhane Jan 08 '21 at 10:05
  • Still the same output @limserhane – Krishan Jan 09 '21 at 05:12
  • Yeah I forgot to tell you that this wouldn’t solve your problem here, but it’s important to do it in general – limserhane Jan 09 '21 at 11:59
  • So is this problem unsolvable? – Krishan Jan 22 '21 at 05:20

0 Answers0