unsigned == signed ?

R

Raj Pashwar

int main()
{
uint x = -1;
int y = -1;
if (x == y)
printf("EQUAL");
else
printf("NOT EQUAL");
}

This code prints "EQUAL". Does this mean that bit comparison is done for
the
equality test? If it doesn't can you give me an example that shows bit
comparison isn't done? I also wanted to know if we can assign a number to
uint & int variables such that "unit var != int var". Thanks so much
 
K

Keith Thompson

Raj Pashwar said:
int main()
{
uint x = -1;
int y = -1;
if (x == y)
printf("EQUAL");
else
printf("NOT EQUAL");
}

This code prints "EQUAL". Does this mean that bit comparison is done for
the
equality test? If it doesn't can you give me an example that shows bit
comparison isn't done? I also wanted to know if we can assign a number to
uint & int variables such that "unit var != int var". Thanks so much

There is no predefined type "uint" in C. I'll assume you meant
"unsigned int".

Here's a corrected version of your program:

#include <stdio.h>

int main(void)
{
unsigned int x = -1;
int y = -1;
if (x == y) {
printf("EQUAL\n");
}
else {
printf("NOT EQUAL\n");
}
return 0;
}

There's actually a fair amount of stuff going on here, some of it
not obvious.

The expression "-1" is of type int. The initialization applies an
implicit conversion from int to unsigned int. The rules for such
a conversion (see C99 6.3.1.3p2) mean that the initial value of
x is UINT_MAX. (This is probably 4294967295 on a typical 32-bit
system, but other values are possible.)

The comparison "x == y" is comparing an unsigned int value to a
(signed) int value. Before the comparison is performed, the
"usual arithmetic conversions" are applied to the operands (C99
6.5.9p4, 6.3.1.8). In this case, the int operand is converted to
unsigned int. Since y's value is -1, the result is the same as
the result of the conversion in x's initialization.

The result is that "x == y" is comparing UINT_MAX to UINT_MAX,
which of course yields a true value (1).

As it happens, the result is the same that you'd get if the program
just performed bitwise comparisons of the operands. The rules
for conversions and comparisons are defined purely in terms of
the arithmetic *values* of the operands, but the rules are written
in such a way that they can be implemented easily on most systems
(2's-complement representation for signed values).

The latest draft of the C standard is at
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
(that's a 3.7-megabyte PDF document).
 
J

James Kuyper

int main()
{
uint x = -1;

uint is presumably a typedef; it's not a typedef provided by the C
standard itself, so you should have let us know what type it is a
typedef for. I'll presume "unsigned int".
int y = -1;
if (x == y)
printf("EQUAL");
else
printf("NOT EQUAL");
}

This code prints "EQUAL". Does this mean that bit comparison is done for
the
equality test?

No, it means that precisely the same conversion is performed on -1 when
it is used to initialize x, as is performed on the value of y when it is
converted to the type of 'x' for the comparison. Assuming that uint is a
typedef for unsigned int, the result is guaranteed to be UINT_MAX in
both cases.
... If it doesn't can you give me an example that shows bit
comparison isn't done?

Yes. Change 'y' to signed char, and x to unsigned long. If sizeof(signed
char) < sizeof(unsigned long) (which is almost, but not quite, certainly
guaranteed), most of the bits that are set in x won't have any
comparable bits in 'y'. However, the values will still compare equal,
because y's value of -1 will be converted to ULONG_MAX before the
conversion.

In the unlikely event that you can locate an implementation where 'int'
uses a 1's complement or sign-magnitude representation, you'll find that
you still get exactly the same result, which ALSO proves that it's a
value comparison, not a bit comparison. That's because x and y will have
very different bit patterns on such a system.
... I also wanted to know if we can assign a number to
uint & int variables such that "unit var != int var". Thanks so much

Not as long as the number is within the range [INT_MIN, INT_MAX].
Because the same conversions are performed in both cases, the values
necessarily compare equal.
 
Q

Quentin Pope

int main()
{
uint x = -1;
int y = -1;
if (x == y)
printf("EQUAL");
else
printf("NOT EQUAL");
}

This code prints "EQUAL". Does this mean that bit comparison is done for
the
equality test? If it doesn't can you give me an example that shows bit
comparison isn't done?

no ! unsigned int, and signed int are very different the way they are
represented in bits. therefore, when you to compare the 2 different types
(like comparing apples and oranges) one of them has to be converted, in
this
case, the 'int' is converted to a 'uint', and becomes 0, since unsigned
numbers cannot be less then zero.
and besides, the == operator it *not* a bit comparison operator, it is a
variable comparison operator, if you want to do bit comparison you use the
bitwise operators, &,|,^,~. (and, or, exclusive or, not. respectively)
I also wanted to know if we can assign a number
to uint & int variables such that "unit var != int var". Thanks so much

yes, if unit var = 1, and int var is any value other than 1 (-1, 0, -10,
10,
100, whatever) then they will be 'not equal' if you use the operator '!='
for example:

uint x = 1;
int y = -1;
if (x == y)
printf("EQUAL");
else
printf("NOT EQUAL");

will print NOT EQUAL since y is converted to an unsigned int and becomes
0
 
J

James Kuyper

yes, if unit var = 1, and int var is any value other than 1 (-1, 0, -10,
10,
100, whatever) then they will be 'not equal' if you use the operator '!='
for example:

uint x = 1;
int y = -1;

You've not using the same initializer for x and for y; I believe that's
what he meant when he referred to assigning "a number to" both variables.
 
K

Keith Thompson

Quentin Pope said:
no ! unsigned int, and signed int are very different the way they are
represented in bits.

They're not all that different. In fact, in the absence of padding bits
and/or trap representations, the language guarantees that a value that's
representable as int and unsigned int (i.e., in the range 0 .. INT_MAX)
has the same representation in both types.
therefore, when you to compare the 2 different types
(like comparing apples and oranges) one of them has to be converted, in
this
case, the 'int' is converted to a 'uint', and becomes 0, since unsigned
numbers cannot be less then zero.

It's true that one of them is converted. This is because the language
standard says so; it's not a consequence of their representations. The
language *could* have defined "==" as a bitwise comparison (and in fact
that would have yielded the same results for int vs. unsigned int
comparisonms on 2's-complement systems).

But you're mistaken about the semantics of the conversion. When an
integer value is converted to an unsigned type, and the value cannot be
represented in the target type, " 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" (C99 6.3.1.3p2). In this particular case, convering the int value
-1 to unsigned int yields UINT_MAX.
and besides, the == operator it *not* a bit comparison operator, it is a
variable comparison operator, if you want to do bit comparison you use the
bitwise operators, &,|,^,~. (and, or, exclusive or, not. respectively)

It's more accurate to say that it's a *value* comparison operator; there
needn't be any variables involved (consider "1 + 1 == 2").

The bitwise operators don't do comparisons. If you want to do
a bitwise equality comparison, the memcmp() function is probably
the best approach. Or you could treat the objects as arrays of
unsigned char and compare the element values (that's basically what
memcmp() does).
yes, if unit var = 1, and int var is any value other than 1 (-1, 0, -10,
10,
100, whatever) then they will be 'not equal' if you use the operator '!='
for example:

uint x = 1;
int y = -1;
if (x == y)
printf("EQUAL");
else
printf("NOT EQUAL");

will print NOT EQUAL since y is converted to an unsigned int and becomes
0

No, it will print NOT EQUAL because y is converted to an unsigned int
and becomes UINT_MAX (typically 4294967295), which is not equal to 1.
You'd get the same result if "==" did a bitwise comparison.
 
B

Ben Bacarisse

Quentin Pope said:
no ! unsigned int, and signed int are very different the way they are
represented in bits. therefore, when you to compare the 2 different types
(like comparing apples and oranges) one of them has to be converted, in
this
case, the 'int' is converted to a 'uint', and becomes 0, since unsigned
numbers cannot be less then zero.

Not zero, but UINT_MAX.
and besides, the == operator it *not* a bit comparison operator, it is a
variable comparison operator, if you want to do bit comparison you use the
bitwise operators, &,|,^,~. (and, or, exclusive or, not. respectively)


yes, if unit var = 1, and int var is any value other than 1 (-1, 0, -10,
10,
100, whatever) then they will be 'not equal' if you use the operator '!='
for example:

uint x = 1;
int y = -1;
if (x == y)
printf("EQUAL");
else
printf("NOT EQUAL");

will print NOT EQUAL since y is converted to an unsigned int and becomes
0

See above!
 
J

J. J. Farrell

Quentin said:
no ! unsigned int, and signed int are very different the way they are
represented in bits. therefore, when you to compare the 2 different types
(like comparing apples and oranges) one of them has to be converted, in
this case, the 'int' is converted to a 'uint', and becomes 0, since
unsigned numbers cannot be less then zero.

Is this meant to be a joke? Or is -1 equal to 0 where you come from?
 
Q

Quentin Pope

They're not all that different. In fact, in the absence of padding bits
and/or trap representations, the language guarantees that a value that's
representable as int and unsigned int (i.e., in the range 0 .. INT_MAX)
has the same representation in both types.


It's true that one of them is converted. This is because the language
standard says so; it's not a consequence of their representations. The
language *could* have defined "==" as a bitwise comparison (and in fact
that would have yielded the same results for int vs. unsigned int
comparisonms on 2's-complement systems).

But you're mistaken about the semantics of the conversion. When an
integer value is converted to an unsigned type, and the value cannot be
represented in the target type, " 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" (C99 6.3.1.3p2). In this particular case, convering the int value
-1 to unsigned int yields UINT_MAX.


It's more accurate to say that it's a *value* comparison operator; there
needn't be any variables involved (consider "1 + 1 == 2").

The bitwise operators don't do comparisons. If you want to do a bitwise
equality comparison, the memcmp() function is probably the best
approach. Or you could treat the objects as arrays of unsigned char and
compare the element values (that's basically what memcmp() does).


No, it will print NOT EQUAL because y is converted to an unsigned int
and becomes UINT_MAX (typically 4294967295), which is not equal to 1.
You'd get the same result if "==" did a bitwise comparison.

true, my mistake.
however the values are converted first. to prove it, try this
long x = -1; /* (32 bit, signed) */
unit y = -1; /* (16 bit, unsigned) */
if (x == y) printf("EQUAL");
will print EQUAL !
 
J

James Kuyper

On 10/12/2011 12:04 PM, Quentin Pope wrote:
....
true, my mistake.
however the values are converted first. to prove it, try this
long x = -1; /* (32 bit, signed) */
unit y = -1; /* (16 bit, unsigned) */
uint?

if (x == y) printf("EQUAL");
will print EQUAL !

Of course, and that's fully consistent with what Keith said.
 
K

Keith Thompson

Quentin Pope said:
true, my mistake.
however the values are converted first. to prove it, try this
long x = -1; /* (32 bit, signed) */
unit y = -1; /* (16 bit, unsigned) */

What makes you think that long is 32 bits and uint (unsigned int?) is
16 bits? They're *at least* those widths, but they could be wider.
(I suspect that int is actually 32 bits on your system.)
if (x == y) printf("EQUAL");
will print EQUAL !

Not if long is wider than int, as you assert. (More precisely, not
if long can represent all the values of unsigned int.) On such
a system, y will be initialized to UINT_MAX, which is 65535.
In the comparison, the "usual arithmetic conversions" will promote
the value of y from unsigned int to (signed) long, resulting in
an equality comparison between 65535 and -1, both of type long.
It will not print "EQUAL".

On the other hand, if int and long are both 32 bits, then both x
and y are converted to unsigned long, so the comparison is between
ULONG_MAX and ULONG_MAX; in that case, it will print "EQUAL".

And why do you insist on using the name "uint"? We've said before
that there is no such predefined type in C. If you mean "unsigned
int", please say "unsigned int". If you really want to call it
"uint", provide a typedef. (For all we know, "uint" could be a
typedef for _Bool.)
 
P

Phil Carmody

Raj Pashwar said:
int main()
{
uint x = -1;
int y = -1;
if (x == y)
printf("EQUAL");
else
printf("NOT EQUAL");
}

This code prints "EQUAL". Does this mean that bit comparison is done for
the
equality test? If it doesn't can you give me an example that shows bit
comparison isn't done? I also wanted to know if we can assign a number to
uint & int variables such that "unit var != int var". Thanks so much

C will only compare equal types. In order to perform what looks
like a comparison between unequal types, an implicit conversion
is made first such that the things actually being compared are
the same type. See the description of the '==' operator in the
standard (google for n1256.pdf if you don't already have a copy).

Phil
 
P

Phil Carmody

Ben Bacarisse said:
Not zero, but UINT_MAX.

He looks like he's under the misapprehension that the conversion is a
saturating one (anything that goes out of bounds gets mapped onto the
value just inside the bound that was exceeded.

So I think the better correction is the mathematical expression
UINT_MAX+1+x
Which for x==-1 is UINT_MAX, as you say.
But for x==2 it's UINT_MAX-1, etc.
See above!

Yup, I'm sure he thinks it saturates.

Phil
 
B

Ben Bacarisse

Phil Carmody said:
He looks like he's under the misapprehension that the conversion is a
saturating one (anything that goes out of bounds gets mapped onto the
value just inside the bound that was exceeded.

So I think the better correction is the mathematical expression
UINT_MAX+1+x
Which for x==-1 is UINT_MAX, as you say.
But for x==2 it's UINT_MAX-1, etc.

It is indeed better, but these details had already been explained by
other replies to the OP when I posted. All I was doing was pointing out
an uncorrected detail in another reply. (And I was feeling lazy.)

<snip>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top