473,480 Members | 1,876 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Integer subtraction problem, help!

hi
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
d = a - b;
printf("%d", c < d);
it prints 1 correctly.

I am stumped, please help! i guess something wrong happens during the
comparison, i dont know what.
If i just retain my second method which works, is everything ok? or is
there some risk?

thanks a lot
bruce

Nov 14 '05 #1
5 6501
In article <11*********************@l41g2000cwc.googlegroups. com>,
br*************@gmail.com wrote:
hi
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).


If you mean 0xffffffff, that is definitely not the same as -1.

Take a good book about C and check out _exactly_ what types the various
operands have.
Nov 14 '05 #2
From: br*************@gmail.com

In two different articles,
<11**********************@f14g2000cwb.googlegroups .com>
and
<11*********************@l41g2000cwc.googlegroups. com>
<br*************@gmail.com> wrote:
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
<news:11*********************@l41g2000cwc.googlegr oups.com>.
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.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #3
br*************@gmail.com wrote:
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
d = a - b;
printf("%d", c < d);
it prints 1 correctly.


You didn't post exact code, so I'm going to make some assumptions:
- You're on a machine with 32-bit ints
- 'b' is an unsigned int (A signed int can't hold 0x80000000)
- 'c' is a signed int which holds -1 (not ffffffff)
- 'd' is a signed int;

Now, 0x80000000 (in decimal, 2147483648) is too big to fit
in a signed int, so the compiler treats it as an unsigned int.
So (a - b) has type "unsigned int" and value 0.

So we have reduced the problem to the old C 'flaw' of signed-
unsigned comparisons. You would get the same result if
you wrote:
printf("%d", -1 < 0u);

In C, binary operators (that is, operators that take 2 operands)
must have both operands the same type. You gave it different
types (one is signed int, the other unsigned int). The compiler
'solves' this problem by converting the signed int to unsigned,
so it ends up doing the comparison 4294967295 < 0 , which
turns out to be false as you have seen.

In your case with 'd', you are comparing two ints, so
no conversions occur, and -1 < 0 is of course true.

In your specific example you can fix the problem like this:
printf("%d\n", c < (int)(a - b));

But if (a - b) did not hold a valid int value (eg. if a is
0x80000000 and b is 0), then you have undefined behaviour.
So in general, if you need to compare the full range of
signed ints with the full range of unsigned ints, you would
need a function like this:

int less_than(int a, unsigned int b)
{
if (b > INT_MAX) return 0;
return a < (int)b;
}

Nov 14 '05 #4
<posted & mailed>

br*************@gmail.com wrote:
hi
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
d = a - b;
printf("%d", c < d);
it prints 1 correctly.

I am stumped, please help! i guess something wrong happens during the
comparison, i dont know what.
If i just retain my second method which works, is everything ok? or is
there some risk?

thanks a lot
bruce


I'll assume that all of the other issues are taken care of and simply point
out math issues here.

a) 0x80000000 - (-1) = 0x80000001 --> Double negative is positive, so (--1)
is equivalent to (+1). Watch this carefully.

b) 0x80000000 < 0x80000001 is true, yes, but the integer value of "true" is
implementation specific...so tread lightly here. :-)

Just words of caution.

--
Tom Cameron
tom<at>drdabbles<dot>us
http://drdabbles.us
Nov 14 '05 #5
Thomas Cameron wrote:
br*************@gmail.com wrote:

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).
a) 0x80000000 - (-1) = 0x80000001 --> Double negative is
positive, so (--1) is equivalent to (+1). Watch this carefully.


That issue never came up in the OP example. 0x80000000 was being
subtracted from 0x80000000. (allegedly).
b) 0x80000000 < 0x80000001 is true, yes, but the integer value
of "true" is implementation specific...so tread lightly here. :-)


The integer value of a '<' operation must be either 0 or 1.

Nov 14 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
8235
by: da Vinci | last post by:
Hi Gents, This is what I am trying to do. Say you have a double or a float with the value 14.5624 for example. How could I take that variable and get the 14 into an integer variable and the...
3
4024
by: Gus Tabares | last post by:
Hello all, I'm having a bit of trouble understanding a snippet of code in the K&R book I'm reading. Basically it's something like this: int ndigit; for (i = 0; i < 10; i++) ndigit = 0; ...
20
9101
by: GS | last post by:
The stdint.h header definition mentions five integer categories, 1) exact width, eg., int32_t 2) at least as wide as, eg., int_least32_t 3) as fast as possible but at least as wide as, eg.,...
25
521
by: bruce.james.lee | last post by:
hi 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,...
5
2905
by: sathyashrayan | last post by:
Group, I have some doubts in the following program. ------------------program--------------------- /* ** Make an ascii binary string into an integer. */ #include <string.h> unsigned int...
19
2039
by: junky_fellow | last post by:
How the unsigned to signed integet conversion is done ? For eg: unsigned int ui = 100; int si = ui; What will be the value if "si" is printed ? How this conversion is done ? Thanx for any...
27
4492
by: REH | last post by:
I asked this on c.l.c++, but they suggested you folks may be better able to answer. Basically, I am trying to write code to detect overflows in signed integer math. I am trying to make it as...
9
38466
by: Dante | last post by:
I'm converting a C# program to VB.net, but i'm having problems converting a integer to a byte in the same way as the c# program does. //C# program int i = 137694; byte b = (byte) i; //b...
25
6207
by: junky_fellow | last post by:
Is there any way by which the overflow during addition of two integers may be detected ? eg. suppose we have three unsigned integers, a ,b, c. we are doing a check like if ((a +b) > c) do...
0
7039
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
6904
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7037
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7080
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
6735
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
1
4770
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
1296
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
558
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
176
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.