(32 intermediate revisions by the same user not shown)
Line 1: Line 1:
<syntaxhighlight lang="c">
+
<metadesc>Undefined value in C language, sequence point</metadesc>
main()
+
===What's the output?===
 +
<syntaxhighlight lang="c" name="undefined_value_2">
 +
#include <stdio.h>
 +
int main()
 
{
 
{
   int a=2;
+
   int a = 2;
   a=++a/a++;
+
   a = a++;
   printf("%d", b);
+
   printf("%d", a);
 +
 
 +
  return 0;
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Solution===
+
==={{Template:Author|Arjun Suresh|{{arjunweb}} }}===
  
The answer to this is "Undefined". C standard says that the side effects of an operation (for b = ++a; modification of a is a side-effect) need to be completed only before the next [https://en.wikipedia.org/wiki/Sequence_point sequence point]. This relaxation is given so that the compiler would be able to generate the most optimal code (which run faster). But as a consequence, programmer shouldn't do a read and a write from a memory location within a sequence point or otherwise the result would be undefined.  
+
The answer to this is "Undefined". C standard says that the side effects of an operation (for b = a++; modification of a is a side-effect) need to be completed only before the next [https://en.wikipedia.org/wiki/Sequence_point sequence point]. This relaxation is given so that the compiler would be able to generate the most optimal code (which run faster). But as a consequence, programmer shouldn't do multiple writes to a memory location within a sequence point or otherwise the result would be undefined.  
  
So, in the statement a = ++a / a++;
+
Undefined behavior can occur if ''Between two consecutive sequence points, an object is modified more than once, or is modified and the prior value is read other than to determine the value to be stored''
  
++a / a++ can return only 1 value (3/3 = 1 or 3/2 = 1). But there is a side effect of post increment a++, which can happen anytime before the next sequence point. So, the answer can be 1+1 = 2 or simply 1. But as per C standard for these codes, the output is simply '''UNDEFINED'''
+
So, in the statement
 +
a = a++;
  
{{Template:FB}}
+
There is a side effect on $a$, which can happen anytime before the next sequence point. So, as per C standard, the output is simply '''UNDEFINED'''. This is shown by the output from three different compilers gcc, icc and clang on an Ubuntu system.
  
 +
asuresh@parambara:~$ gcc -Wall undefined.c
 +
undefined.c: In function ‘main’:
 +
undefined.c:5:6: warning: operation on ‘a’ may be undefined [-Wsequence-point]
 +
    a = a++;
 +
      ^
 +
asuresh@parambara:~$ ./a.out
 +
2
 +
asuresh@parambara:~$ icc -Wall undefined.c
 +
asuresh@parambara:~$ ./a.out
 +
3
 +
asuresh@parambara:~$ clang -Wall undefined.c
 +
asuresh@parambara:~$ ./a.out
 +
2
 +
 +
Undefined value means compiler can give any value. i.e.; different compilers or even different versions of the same compiler can give different answers. As per C standard, no programmer should write this code. This is different from compiler dependent, in which case the output is clearly defined by the compiler and programmer can write those code as long as he is aware of the compiler. Example of compiler dependent code is sizeof(int).
 +
 +
===Precedence Rule===
 +
Undefined behaviour is happening not because C is violating precedence rule. Precedence (and associativity which is used when precedence of operators are same) rule is used to specify the operands for operations. But the actual execution order might be different. For example:
 +
x = a*b+c*d;
 +
 +
After applying precedence rule, we get
 +
x = ((a*b) + (c*d));
 +
 +
Thus the first $*$ has operands $a$ and $b$, the second $*$ has operands $c$ and $d$, the $+$ has operands returned by the result of two $*$ and $=$ has left operand $x$ and right operand the result of $+$. But, during execution $(a*b)$ or $(c*d)$ can occur first as both these won't be violating the precedence rule.
 +
 +
Similarly, if we take
 +
x = i++ * ++i;
 +
 +
After applying precedence rule, we get
 +
x = ((i++) * (++i));
 +
$i$++ or ++$i$ can happen first. Suppose ++$i$ happened first. It'll surely return $i+1$. But whether this incremented $i$ is used by $i$++ is not guaranteed. This increment can happen to $i$ ANYTIME before the next sequence point, which here is the ; at the end of the expression. This makes this code produce undefined behaviour. 
 +
 +
[http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points Discussion in stackoverflow]
 +
{{Template:FBD}}
  
  
<disqus/>
 
  
 
[[Category:Coding Questions]]
 
[[Category:Coding Questions]]

Latest revision as of 18:13, 23 July 2014

What's the output?

<syntaxhighlight lang="c" name="undefined_value_2">

  1. include <stdio.h>

int main() {

  int a = 2;
  a = a++;
  printf("%d", a);
  
  return 0;

} </syntaxhighlight>

Solution by Arjun Suresh

The answer to this is "Undefined". C standard says that the side effects of an operation (for b = a++; modification of a is a side-effect) need to be completed only before the next sequence point. This relaxation is given so that the compiler would be able to generate the most optimal code (which run faster). But as a consequence, programmer shouldn't do multiple writes to a memory location within a sequence point or otherwise the result would be undefined.

Undefined behavior can occur if Between two consecutive sequence points, an object is modified more than once, or is modified and the prior value is read other than to determine the value to be stored

So, in the statement

a = a++;

There is a side effect on $a$, which can happen anytime before the next sequence point. So, as per C standard, the output is simply UNDEFINED. This is shown by the output from three different compilers gcc, icc and clang on an Ubuntu system.

asuresh@parambara:~$ gcc -Wall undefined.c
undefined.c: In function ‘main’:
undefined.c:5:6: warning: operation on ‘a’ may be undefined [-Wsequence-point]
   a = a++;
     ^
asuresh@parambara:~$ ./a.out
2
asuresh@parambara:~$ icc -Wall undefined.c
asuresh@parambara:~$ ./a.out
3
asuresh@parambara:~$ clang -Wall undefined.c
asuresh@parambara:~$ ./a.out
2

Undefined value means compiler can give any value. i.e.; different compilers or even different versions of the same compiler can give different answers. As per C standard, no programmer should write this code. This is different from compiler dependent, in which case the output is clearly defined by the compiler and programmer can write those code as long as he is aware of the compiler. Example of compiler dependent code is sizeof(int).

Precedence Rule

Undefined behaviour is happening not because C is violating precedence rule. Precedence (and associativity which is used when precedence of operators are same) rule is used to specify the operands for operations. But the actual execution order might be different. For example:

x = a*b+c*d;

After applying precedence rule, we get

x = ((a*b) + (c*d));

Thus the first $*$ has operands $a$ and $b$, the second $*$ has operands $c$ and $d$, the $+$ has operands returned by the result of two $*$ and $=$ has left operand $x$ and right operand the result of $+$. But, during execution $(a*b)$ or $(c*d)$ can occur first as both these won't be violating the precedence rule.

Similarly, if we take

x = i++ * ++i;

After applying precedence rule, we get

x = ((i++) * (++i));

$i$++ or ++$i$ can happen first. Suppose ++$i$ happened first. It'll surely return $i+1$. But whether this incremented $i$ is used by $i$++ is not guaranteed. This increment can happen to $i$ ANYTIME before the next sequence point, which here is the ; at the end of the expression. This makes this code produce undefined behaviour.

Discussion in stackoverflow



blog comments powered by Disqus

<syntaxhighlight lang="c"> main() {

  int a=2;
  a=++a/a++;
  printf("%d", b);

} </syntaxhighlight>

Solution[edit]

The answer to this is "Undefined". C standard says that the side effects of an operation (for b = ++a; modification of a is a side-effect) need to be completed only before the next sequence point. This relaxation is given so that the compiler would be able to generate the most optimal code (which run faster). But as a consequence, programmer shouldn't do a read and a write from a memory location within a sequence point or otherwise the result would be undefined.

So, in the statement a = ++a / a++;

++a / a++ can return only 1 value (3/3 = 1 or 3/2 = 1). But there is a side effect of post increment a++, which can happen anytime before the next sequence point. So, the answer can be 1+1 = 2 or simply 1. But as per C standard for these codes, the output is simply UNDEFINED





blog comments powered by Disqus