From: (e-mail address removed)
In two different articles,
<
[email protected]>
and
<
[email protected]>
i have a problem with integer subtraction in C.
printf("%d", c < (a - b));
a is got from a #define and is 0x80000000 and b is got from input and
is also 0x80000000.
c is ffffffff (-1).
Now, this should print 1 (true) but it prints 0!
If I modify this to
[here is where the two articles differ]
d = c < (a - b);
printf("%d", d);
it prints 1 correctly.
This would imply a compiler bug.
d = a - b;
printf("%d", c < d);
it prints 1 correctly.
This would imply something else entirely.
I am stumped, please help! i guess something wrong happens during the
comparison, i dont know what.
The situation here is a bit like a guy who drives into an auto shop
with a problem. The mechanic looks at the car: "I don't see anything
wrong here." "Oh, *this* isn't the car with the problem. I drove
this one in because the other one won't start!"
Presumably something *is* wrong, but you have not brought in the
actual code, just some little snippet from it. (In the analogy
above, the guy might have brought in the cigarette lighter from
the faulty car.
) Still, one can make a guess at your complete
program:
% cat t.c
#include <stdio.h>
#define a 0x80000000
int main(void) {
int b = 0x80000000, c = 0xffffffff, d;
printf("c < (a - b): %d\n", c < (a - b)); /* line 8 */
d = a - b;
printf("c < d: %d\n", c < d);
return 0;
}
% cc -ansi -pedantic -o t t.c
% ./t
c < (a - b): 0
c < d: 1
%
This has the same symptoms you describe in
<Note what happens if we ask the compiler (GNU's GCC, in this case)
for "maximal warnings":
% cc -O -Wall -W -ansi -pedantic -o t t.c
t.c: In function `main':
t.c:8: warning: comparison between signed and unsigned
%
(line 8 is the commented printf() call). This is your clue as to
what is wrong.
On a 32-bit-"int" system like the one I used here, the constant
0x80000000 has type "unsigned int". The expression:
c < (0x80000000 - b)
has three operands: one "int" (c), one "unsigned int" (0x80000000),
and one more "int" (b). The parenthesized sub-expression is grouped
first, and a C compiler must find the type to use for the result of
the subtraction based on nothing but the types of the two operands.
Since one is "unsigned int" and the other is plain (signed) "int",
the computation will be done with unsigned arithmetic, producing an
unsigned int result. The value in b is first converted to unsigned
int, giving 0x80000000U again, and the result is the unsigned int 0,
so this means:
c < 0U
The variable c is of course -1, but this expression does the
comparison by converting c to unsigned int, producing UINT_MAX or
(on this implementation) 4294967295, so this means:
4294967295U < 0U
and of course it is not.
By assigning the result of the subtraction to "d" -- an ordinary
signed int -- we get the second comparison to compare -1 and 0 (two
ordinary signed "int"s), and of course -1 is less than 0.
Note that a more fundamental problem here is that you have defined
"a" as 0x80000000, which is numerically 2147483648, but on your
machine (and the one I used to compile the test case above), INT_MAX
is 2147483647. What happens when you put 2147483648 into a variable
that cannot hold a number bigger than 2147483647? Pretty much the
same thing as when you put ten gallons of water into a five-gallon
bucket: it overflows. To extend this analogy a bit, C does not
specify whether the floor is wood (which warps) or tile (which is
waterproof and does not warp) -- you are on your own at this point.
If you want the language itself to specify the result, avoid this
kind of overflow. If you feel safe in depending on "always having
tile floors" as it were -- that is, if you are sure you will always
use the machine you are using right now -- you can depend on any
additional guarantees it makes. Here in the comp.lang.c newsgroup,
thuogh, we generally try to discourage this kind of "depending on
the machine", at least whenever possible; and we try not to talk
too much about the specifics of any one machine, since C runs on
so many different machines with different behaviors.