I'm getting different results for the same code with different compilers. Is this a undefined behaivour?
#include <stdio.h>
int a;
int b=10;
int puan_ekle(int puan, int bonus){
puan=puan+bonus;
a=puan-5;
bonus--;
return bonus;
}
int main(){
a=23;
printf("Result1 %d \n", a);
a=a+puan_ekle(a,b);
printf("Result2 %d \n", a);
a=a+puan_ekle(a,b);
printf("Result3 %d \n", a);
}
The behavior is unspecified, not undefined.
The C standard distinguishes these. C 2018 3.4.4 1 says:
And 3.4.3 1 says:
In some situations, when an object is both used for its value and modified, a rule in the C standard makes the behavior undefined. 6.5 2 says:
Let’s see how this applies to
a=a+puan_ekle(a,b);. In this expression:ais modified by thea=.ais used in thea+.ais used in the arguments(a,b).puan_ekle,ais modified witha=puan-5;.The modifications are side effects—they are something that happens separately from computing the value of the expression. If either of the modifications, 1 or 4, is unsequenced relative to any of the other items, the behavior is undefined.
Regarding 1, 6.5.16 3 says:
So 1 is sequenced after 2 and 3. Since 4 is a side effect, not a value computation, we still have to consider the relationship of 1 and 4. To resolve this, we will consider sequence points. Per 5.1.2.3, “The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B.”
Next we need to know what a full expression is and that there is a sequence point after each full expression. 6.8 4 says:
This means that every statement inside
puan_ekleis or contains a full expression:puan=puan+bonusis a full expression,a=puan-5is a full expression,bonus--is a full expression, and thebonusinreturn bonusis a full expression. So, aftera=puan-5, there is a sequence point.Since, for
a=, the side effect of modifyingais sequenced after the value computations of the operands. Evaluating those operands includes calling the function, which includes its sequence points. So effect 4, modifyingaina=puan-5;, must be completed before execution continues to the next statement, and hence must be completed before effect 1. So 1 and 4 are sequenced.What is left is to consider effect 4 with respect to 2 and 3. 4 is sequenced after 3 because a function call is sequenced after evaluation of its arguments, per 6.5.2.2 10:
Now all we have left is the sequencing of 2 relative to 4. In this, there is no specification of which is first. The evaluations of the operands of
+are unsequenced, so, fora+puan_ekle(a,b), a C implementation may do eitherafirst orpuan_ekle(a,b)first. However, whichever it does first, there is a sequence point between 2 and 4:ais evaluated first, then, before the function call, there is a sequence point (per 6.5.2.2 10, quoted above).puan_ekle(a,b)is evaluated first, there is a sequence point after the full expressiona=puan-5.Thus, 2 and 4 are indeterminately sequenced. (5.1.2.3 3: “… Evaluations A and B are indeterminately sequenced when A is sequenced either before or after B, but it is unspecified which…”) But they are not unsequenced, so there is no undefined behavior. The behavior is unspecified because there are two possibilities. The C implementation is required implement one of those two possibilities, which is different from undefined behavior, in which there would be no requirements.