|
On 12/05/2019 12:08, Philippe Verdy wrote:
Le dim. 12 mai 2019 à 07:38, Andrew Gierth <andrew@tao11.riddles.org.uk> a écrit :"Philippe" == Philippe Verdy <verdy_p@wanadoo.fr> writes:>> fprintf(stderr,"n=%lli x=%llx >> <≤=≥>:%i%i%i%i%i\n",n,n,n<0,n<=0,n==0,n>=0,n>0); >> if (n<0) n=-n; >> fprintf(stderr,"n=%lli x=%llx >> <≤=≥>:%i%i%i%i%i\n",n,n,n<0,n<=0,n==0,n>=0,n>0); >> >> produces (GNU compiler): >> >> n=-9223372036854775808 x=8000000000000000 <≤=≥>:11000 >> n=-9223372036854775808 x=8000000000000000 <≤=≥>:01010 Philippe> What you show here is a bug of the C compiler in its Philippe> optimizer Possibly unfortunately, this is not a bug. The program invokes undefined behavior when it does n=-n on the the value shown; the compiler is entitled to produce any output at all as a result. In this case it's fairly obvious what happened: after seeing the line if (n<0) n=-n; the compiler is entitled to assume that n>=0 is true regardless of the prior value of n, since only undefined behavior could cause that not to be the case and the compiler is allowed to assume that undefined behavior never occurs. So in the second fprintf, the compiler can optimize (n>=0) to a constant 1, and (n<0) to a constant 0, while still computing the remaining tests.Such compiler assumption is wrong and it's clearly a bug in its optimizer , trying to infer constant values from code whose evaluation is clearly not constant here, that line does not mean that the result in n is necessarily positive. so it cannot assume that n>=0 after this line (even if C indicates that the result is undefined, then the further tests of n<0 and n>=0 must still be computed: an undefined value has no *constant* sign).
[snip] "the result is undefined..." and "... and undefined value..."Sorry, but it seems that you are not aware of what "undefined behavior" (UB) means in C. There is no "undefined result" and neither "undefined value".
That jargon is not generic CS jargon, but it is a concept mandated by the standard.
Basically, once your program triggers UB even in a single spot in a gazillion lines of code, the whole gazillion lines are garbage.
Quoting from section 3.4.3 of C99 draft standard (N1256), emphasis mine: ========================================================== 3.4.3 1 undefined behaviorbehavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes /no requirements/
2NOTE Possible undefined behavior ranges from /ignoring the situation completely/ with /unpredictable results/, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
3EXAMPLE An example of undefined behavior is the behavior on integer overflow.
==========================================================So there is no requirement for any conforming implementation to do anything sensible when UB is invoked.
Note also that it is not /the value/ that it is undefined. Any program construct that invokes undefined behavior renders /the whole program/ garbage, from the POV of a conforming implementation.
To stress that ANYTHING could happen, it is a common joke among C programmers to say that if you trigger undefined behavior you get "demons coming out of your nose", usually abbreviated to "you get nasal demons".
An interesting set of articles from the blog of John Regehr (Professor of Computer Science, University of Utah, USA) that may shed some light on the rationale behind UB:
https://blog.regehr.org/archives/213 Cheers! -- Lorenzo