[sane-devel] C undefined operations in sane-backends-1.0.7-b

Ingo Wilken Ingo.Wilken@Informatik.Uni-Oldenburg.DE
Thu, 24 Jan 2002 15:19:31 +0100 (MET)


> i do no understand this discussion about the code fragment
>         bit =3D ++bit % 8;
> 1. Since 20 years, C is my favorite programming language
> 2. Since some years, I give classes in C
> 3. The code line "bit =3D ++bit % 8", is fully correct.

No.  'bit' is modified twice between sequence points, so the behaviour
is undefined.  See comp.lang.c FAQ, section 3.1, 3.2, 3.3, 3.3b, and
others.  (http://www.faqs.org/)

Basically, the 'store' part of the pre-increment can happen any time
this expression is evaluated.  C guarantees that 'bit' will be
incremented before the next sequence point and that it uses the
incremented value in the rest of the expression, but it does not say
that the incremented value gets stored to 'bit' immediately.

For example, the compiler can expand the expression to this:
	tmp1 = bit;			# Fetch into register
	tmp1 = tmp1 + 1;	# increment part of ++bit
	tmp2 = tmp1 % 8;	# rest of expression
	bit = tmp2;			# assignment
	bit = tmp1;			# store part of ++bit
or it can swap the last two lines (which is the desired result)
	tmp1 = bit;
	tmp1 = tmp1 + 1;	# increment part of ++bit
	tmp2 = tmp1 % 8;	# rest of expression
	bit = tmp1;			# store part of ++bit
	bit = tmp2;			# assignment
or it can even do something like (assuming a register-starved CPU
with fast memory-to-memory operations):
	tmp1 = bit;			# Fetch into register
	tmp1 = tmp1 + 1;	# Increment register
	tmp1 = tmp1 % 8;	# rest of expression
	bit = tmp1;			# assignment
	bit = bit + 1;		# increment memory location
Depending on the machine architecture, it can even do the increment-store
in parallel with the other operations, so you might get a race condition
and partial writes from both store operations - or a CPU exception.

Anyway, the expression is easily fixed.  Either use:
	++bit;
	bit %= 8;
or
	bit = (bit+1) % 8;

Regards,
Ingo