Author: Dieter Buerssner
Date: 11:11:02 07/04/03
Go up one level in this thread
On July 04, 2003 at 13:56:09, Normand M. Blais wrote:
>First, I would like to thanks everybody for their help. No one can succeed
>alone.
>
>The problem that I had was that my program would not run properly when compile
>with optimization for speed but would run ok in debug version or in release
>version with default optimization. I found that the problem was with a specific
>function and the way it was coded:
>
>// This fuction runs with no problem in debug version or release version with
>// default optimization.
>// But it fails in release version with optimization for speed.
>inline int s2i(const char *str)
>{
> // input: a square name (string) (ex: e4)
> // output: a square number (integer) (ex: 36)
>
> int sq = (*str - 'a') + (8 * (8 - (*(++str) - '0')));
>
> if (sq >= 0 && sq <= 63) return sq;
>
> return -1;
>}
>Why the first version of the function causes problem is not clear to me.
Because it is wrong.
From the C-FAQ:
Section 4. Expressions
4.1: Why doesn't this code:
a[i] = i++;
work?
A: The subexpression i++ causes a side effect -- it modifies i's
value -- which leads to undefined behavior if i is also
referenced elsewhere in the same expression. (Note that
although the language in K&R suggests that the behavior of this
expression is unspecified, the ANSI/ISO C Standard makes the
stronger statement that it is undefined -- see question 5.23.)
References: ANSI Sec. 3.3 p. 39.
4.2: Under my compiler, the code
int i = 7;
printf("%d\n", i++ * i++);
prints 49. Regardless of the order of evaluation, shouldn't it
print 56?
A: Although the postincrement and postdecrement operators ++ and --
perform the operations after yielding the former value, the
implication of "after" is often misunderstood. It is _not_
guaranteed that the operation is performed immediately after
giving up the previous value and before any other part of the
expression is evaluated. It is merely guaranteed that the
update will be performed sometime before the expression is
considered "finished" (before the next "sequence point," in ANSI
C's terminology). In the example, the compiler chose to
multiply the previous value by itself and to perform both
increments afterwards.
The behavior of code which contains multiple, ambiguous side
effects has always been undefined (see question 5.23). Don't
even try to find out how your compiler implements such things
(contrary to the ill-advised exercises in many C textbooks); as
K&R wisely point out, "if you don't know _how_ they are done on
various machines, that innocence may help to protect you."
References: K&R I Sec. 2.12 p. 50; K&R II Sec. 2.12 p. 54; ANSI
Sec. 3.3 p. 39; CT&P Sec. 3.7 p. 47; PCS Sec. 9.5 pp. 120-1.
(Ignore H&S Sec. 7.12 pp. 190-1, which is obsolete.)
4.3: I've experimented with the code
int i = 2;
i = i++;
on several compilers. Some gave i the value 2, some gave 3, but
one gave 4. I know the behavior is undefined, but how could it
give 4?
A: Undefined behavior means _anything_ can happen. See question
5.23.
5.23: People seem to make a point of distinguishing between
implementation-defined, unspecified, and undefined behavior.
What's the difference?
A: Briefly: implementation-defined means that an implementation
must choose some behavior and document it. Unspecified means
that an implementation should choose some behavior, but need not
document it. Undefined means that absolutely anything might
happen. In no case does the Standard impose requirements; in
the first two cases it occasionally suggests (and may require a
choice from among) a small set of likely behaviors.
If you're interested in writing portable code, you can ignore
the distinctions, as you'll want to avoid code that depends on
any of the three behaviors.
References: ANSI Sec. 1.6, especially the Rationale.
Regards,
Dieter
This page took 0.01 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.