-3
#include<stdio.h>
int main()
{
    int a=5,b=9;
    char ch='c';
    printf("%c %c\n",ch,++ch);
    printf("%d %d\n",a,!!a);
    printf("%d %d %d\n",a=a+2,-a + ++b%a,a<<2);//
    printf("%d",a);
    return 0;
}



/* 
    op
    d d
    5 1
    7 -5 20
    7
*/

output of this c program is weird ,instead of value -4 at second position third line it shows -5 how? i am using devc++IDE

  • 1
    Here we go again. Undefined behavior. Sequence points. Looking for duplicate questions... – Fred Larson May 28 '15 at 19:34
  • possible duplicate of [Why does this (i = ++i % 3) generate a warning: "may be undefined"?](http://stackoverflow.com/questions/7877258/why-does-this-i-i-3-generate-a-warning-may-be-undefined) – Fred Larson May 28 '15 at 19:35
  • 1
    possible duplicate of [Why are these constructs (using ++) undefined behavior?](http://stackoverflow.com/questions/949433/why-are-these-constructs-using-undefined-behavior) – mch May 28 '15 at 19:36
  • 1
    Are you even sure what order the arguments are evaluated? – Weather Vane May 28 '15 at 19:38
  • 1
    Yet more piles of absolute ggrbage code:( Nobody cares about answers to questions like this because nobody writes code like this. Adds negative value to the site. – Martin James May 28 '15 at 23:27

2 Answers2

2

The program could actually show any value or even crash (undefined behaviour), since you are modifying a and using it a second time within the same sequence point. You will have to move the a = a+2 instruction before or after the printf invocation. Same should be done with the ++ch instruction. See this question for further info.

EDIT While the linked question covers the case up to C99, the C11 standard was worded differently. Now the relevant section is §6.5/2.

"If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings."

Here the expression is the whole printf invocation, and the "value computation using the value of the same scalar object" is the use of ch in an additional place in the parameter list, other than the place in which it is changed. Since the evaluations of the parameters are unsequenced (§6.5/3), the "multiple allowable orderings" clause applies.

EDIT 2 Because of §6.5.2.2/10, what precedes might be not appliable if one called f(&ch) (with f altering the stored value) instead of ++ch. I am however not totally sure about this.

Community
  • 1
  • 1
Alberto M
  • 1,057
  • 8
  • 24
  • Could you point me where the standard only allows an argument being passed once? Not for the evaluation order; just that it may crash or causes UB. – too honest for this site May 28 '15 at 19:55
  • You can pass an argument how many times you want, as long as you don't alter it. See the linked question, the accepted answer explains everything. – Alberto M May 28 '15 at 20:00
  • If you refer to the `i = ++i ...` question: well, for the ch operation, the variable is actually onle modified once. The second comment does not cite the standard int he accepted answer. I totally agree that it ambigious, but still not sure about UB (hwoever, according to 6.5 I it's clear it is for multiple side-effects). Not that I would use this anyways; just curious. – too honest for this site May 28 '15 at 20:09
  • The cited answer has an example which is identical to the one in this question, with "only" one altering operation, and explains why that is UB including the corresponding Standard paragraph. – Alberto M May 28 '15 at 20:43
  • I'm referring to the answer linked by me, not by the commenter. – Alberto M May 28 '15 at 20:53
  • For calling a function, that will have its own sequence points, so this behaviour is pretty well defined (but still sequence-dependent). That is exactly where I hang. I would have thought an operator is not different from such a function call. But that might be wrong at least for C. – too honest for this site May 29 '15 at 15:25
0

Different from the first thoughts, this program does actually not show undefined behaviour, as each expression doe not violate (C11, 6.5/2). In brief: each expression only has one side-effect and each expression per se is clearly defined (each would very well work as expression statements or the right side of an assignment).

Suspect are actually just these lines:

printf("%c %c\n",ch,++ch);
printf("%d %d %d\n",a=a+2,-a + ++b%a,a<<2);//

After each sequence point (roughly: function call), all variables are well-defined.

However, the actual values passed to printf vary, as the sequence the expressions for the arguments are evaluated is not defined (5.1.2.3/2 - indeterminately sequenced). So, for the first line, either ch or ch+1 is passed as the first argument, depending which argument expression is evaluated first. The second argument is, however always ch+1.

Comments welcome, please cite the standard, no second/3rd source. Yes, that is a gauntlet thrown down.

Disclaimer: this code is of course crap. This I will not discuss. It is, however, a good exercise for students exactly to enforce the question as asked. (wereas I wonder if there is no other like this already - the ones given in the comments are actually not, as they do exhibit UB). It is vital actually to sensitize programmers for this problem, which is very specific to C-like languages as those do allow side-effects for expressions.

Edit:

After further thinking, I am not that sure anymore. As my chain of prove is missing a link which I cannot find (lack of understanding the english phrases or just being too stupid), I will accept to treat this as UB now. While still in doubt, the behavior is bad however it would be called and has no application beyond as an example for - at least - ambivalent coding. I leave it here in hope, someone might stumble around and show up the final solution.

Thanks @AlbertoM for watering the seed of doubt.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • 1
    Clause 6.5#2 of the C99 specification: "Between the previous and next sequence point [...] the prior value [of a modified object] shall be accessed only to determine the value to be stored." Here the value is instead used also as a function parameter, hence violating the rule. – Alberto M May 29 '15 at 01:05
  • @AlbertoM: Hmm.. I see your point, but I still struggle with this (and I mostly refer to C11-[n1570](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)) . Please consider replacing `++ch` by a function which does exactly the the same (taking &ch as argument). Actually, in C++, '++' would be exactly such a function. Now, if that function would be inlined: why would there be any difference made by the standard? However, I'll have this to settle a bit and think it over (thanks, that was exactly what I wanted: a different viewpoint). – too honest for this site May 29 '15 at 01:28
  • @AlbertoM: Just one thing: 6.5/2 does onlly apply within the evaluation of an expression. it does not, however apply to the evaluation between two seperate expressions as those for two arguments. The examples given in the footnotes (73 iirc for C99) are actually single expressions. – too honest for this site May 29 '15 at 01:35
  • For the "value as a function argument": No, it is the value of the expression `++ch`, not the value of `ch`. The same would be true for `ch++` actually (which just happens to be _identical_ to the value of `ch`). – too honest for this site May 29 '15 at 01:48
  • @AlbertoM: Note there is a difference between C11 and C99 (drafts). C11 does not mention sequence points any more. – too honest for this site May 29 '15 at 02:07
  • Thanks for pointing out the new formulation in C11. I updated my answer to cover the new Standard. EDIT -- I now understood what you meaned when you spoke about function calls. The matter seems less clearly clear-cut as before. I updated my answer again. Thank for pointing out this fine points. – Alberto M May 29 '15 at 14:50
  • @AlbertoM: Welcome. Glad that was no wast of time (as that practice is bad wether it be UB or IS). I just missed a link in my chain of arguments or lack proper understanding. Glad I might not be alone with this:-) – too honest for this site May 29 '15 at 15:00