To elaborate, the second expression has an underflow at 1 - sizeof(int) on an unsigned integer (promotion due to sizeof being unsigned), which is perfectly well defined:
"if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type."
The right shift is fine on a signed or unsigned integer. For the unsigned case (which is this one due to operator precedence), the behavior is well defined. For signed, implementation defined.
EDIT: The right shift is in fact UB assuming sizeof(int) <= 4.
I know of three different ways in which platforms implement shifts by greater than the word size.
I think it's just pointing out the difference between '&' and '&&'.
They do invoke implementation defined behaviour, but not undefined.
return x == (1 && x);
Into this: movl $0, %eax
andl $1, %eax
cmpl %eax, %eax
# Result in %eax
That will (obviously) return 1 every time, because we compare %eax and %eax. The reason for this is that the value of 'x' changes half-way through the computation (Because the computation is done in %eax, which is where 'x' is assumed to be). This is valid because 'x' is uninitalized, so it doesn't have a defined value.It's a code fragment; it's not in a function body. The way I read it, it was simply to document the type of x. 'x' could be a global for all we know.
/* Generated by CIL v. 1.3.7 */
/* print_CIL_Input is true */
#line 1 "cilcode.tmp/ex30.c"
int main(void)
{ int x ;
{
#line 2
return (x == (x != 0));
}
}
From that I think it's safe to say that it's talking about 'x' being an uninitialized variable in a function (Because that's what they put into CIL). This code definitely has the issue from UB that I described above.