My understanding has always been that expressions that mix int and unsigned int would convert all operands to unsigned int, before applying the operator. So that the code would be equivalent to
unsigned int u;
u = (unsigned int) -1;
if(u == (unsigned int) -1) ...;
On 2-complement architectures (are there still any other) a cast from signed to unsigned integer data types of the same length would be a no-op, and preserve the bit pattern 0xFFFFFFFF.
Clang, however, issues a warning that the comparison will never yield true,..
My understanding has always been that expressions that mix int and unsigned int would convert all operands to unsigned int, before applying the operator. So that the code would be equivalent to
unsigned int u;
u = (unsigned int) -1;
if(u == (unsigned int) -1) ...;
On 2-complement architectures (are there still any other) a cast from signed to unsigned integer data types of the same length would be a no-op, and preserve the bit pattern 0xFFFFFFFF.
Clang, however, issues a warning that the comparison will never yield true,..
My "favorite" compiler.
I just tried it and got no warning at all.
this is version 7.0.2
When I ran your code it seemed to work just fine. clang never did know its a$$ from its elbow...
My understanding has always been that expressions that mix int and unsigned int would convert all operands to unsigned int, before applying the operator. So that the code would be equivalent to
unsigned int u;
u = (unsigned int) -1;
if(u == (unsigned int) -1) ...;
On 2-complement architectures (are there still any other) a cast from signed to unsigned integer data types of the same length would be a no-op, and preserve the bit pattern 0xFFFFFFFF.
Clang, however, issues a warning that the comparison will never yield true,..
My understanding has always been that expressions that mix int and unsigned int would convert all operands to unsigned int, before applying the operator. So that the code would be equivalent to
unsigned int u;
u = (unsigned int) -1;
if(u == (unsigned int) -1) ...;
On 2-complement architectures (are there still any other) a cast from signed to unsigned integer data types of the same length would be a no-op, and preserve the bit pattern 0xFFFFFFFF.
-1 is always converted to the biggest unsigned integer value, whatever the architecture, because of the arithmetic of unsigned integers.
Clang, however, issues a warning that the comparison will never yield true,..
clang (3.7) only issues this kind of warning if the signed type is of higher rank than the unsigned type. For example:
unsigned short u = -1;
if (u == -1) { /*...*/
warning: comparison of constant -1 with expression of type 'unsigned short' is always false [-Wtautological-constant-out-of-range-compare]
Otherwise it just complains about a comparison between an integer or an unsigned integer. This latter warning is just here to tell the coder he may do something wrong.
#include <stdio.h>
int main() {
unsigned int u;
u = ~0u;
if (u == ~0u)
puts("OK");
}
on two's complement implementations, there is no real danger with the original code: unsigned int and signed int have the same rank and the latter will be value-converted to the former.
My understanding has always been that expressions that mix int and unsigned int would convert all operands to unsigned int, before applying the operator. So that the code would be equivalent to
unsigned int u;
u = (unsigned int) -1;
if(u == (unsigned int) -1) ...;
On 2-complement architectures (are there still any other) a cast from signed to unsigned integer data types of the same length would be a no-op, and preserve the bit pattern 0xFFFFFFFF.
Clang, however, issues a warning that the comparison will never yield true,..
That's strange becase conversions from signed to unsigned integers are well defined by the standard, -1 converts to max uint, no matter if it uses 2's complement or not.
If the compiler claims the comparison never yields true then it's simply broken.
unsigned short u = -1;
if (u == -1) { /*...*/
warning: comparison of constant -1 with expression of type 'unsigned short' is always false [-Wtautological-constant-out-of-range-compare]
Otherwise it just complains about a comparison between an integer or an unsigned integer. This latter warning is just here to tell the coder he may do something wrong.
#include <stdio.h>
int main() {
unsigned int u;
u = ~0u;
if (u == ~0u)
puts("OK");
}
on two's complement implementations, there is no real danger with the original code: unsigned int and signed int have the same rank and the latter will be value-converted to the former.
It's not so much a matter of "danger", but of expressing intent as clearly as possible. If you want a pattern of all 1s, you can get it easily the way I proposed, and the resulting constant has the right type, so the compiler won't look at it funny.
I am not so sure that the standard guarantees that the -1 will work, anyway. Can you point to the specific paragraph?
I don't have Clang, but this issue is triggered by a bug report on XBoard, where someone tries to compile it for Mac with Clang. The build log contains the following warning:
moves.c:1337:26: warning: comparison of constant -4 with expression of type
'ChessSquare' is always false
[-Wtautological-constant-out-of-range-compare]
if (board[EP_STATUS] == EP_IRON_LION && (board[rt][ft] == WhiteLion ...
~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
Now based on what people remarked here there could be a genuine problem: board[] is declared as ChessSquare, which is an enum type. In the gcc that I am using this is apparently always implemented as (unsigned int). But the range of the enum does not extend beyond 256, so it could very well be that Clang implements it as (unsigned char). In that case there would be a problem, because board[EP_STATUS] = -4; would assign 0xFF to it, which would not be sign extended on conversion to (unsigned int).
I guess I will have to be more careful here, and cast the ChessSquare to (signed char) before doing the comparison.