Integer subtraction problem, help!

  • Thread starter bruce.james.lee
  • Start date
B

bruce.james.lee

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 = c < (a - b);
printf("%d", 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
 
E

Eric Sosman

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!

You seem to have fallen into the pit too many C programmers
dig for themselves: Thinking about representations rather than
values. For example, `ffffffff' is *not* -1; it is (if there's
a `0x' at the beginning) 4294967295. Since `a-b' is zero and `c'
is this large positive number, the output is as expected.
If I modify this to
d = c < (a - b);
printf("%d", d);
it prints 1 correctly.

Did you make any other modifications? Wait: don't answer!
Instead, please post an *actual* *complete* *minimal* example
of the code that baffles you. I'm trying to guess what the
#define's and variable declarations and initializations and
assignments actually looked like, and if my guesses are wide of
the mark I'll give a diagnosis that has nothing to do with your
actual problem. Show the actual problem and somebody will be
likely to help.

Consider: If you're baffled by the inexplicable behavior
of some piece of code, are you in a good position to winnow the
relevant from the irrelevant pieces? No? Then don't try; you're
quite likely (as in this instance) to leave out the important bits.
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?

Impossible to say on the scanty evidence available.
 
M

Martin Ambuhl

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!

Are you _sure_ that an int can hold such values?

The following code should produce, on most implementations, a number of
warnings. Pay attention to the warnings, and then think about what they
and the possibly strange-looking output might mean:

#include <stdio.h>

int main(void)
{
unsigned short usc = 0xffffffff, usa = 0x80000000, usb = 0x80000000;
/* the above line leads to truncation in my implementation, shorts
not being 32 bits */
unsigned long ulc = 0xffffffffL, ula = 0x80000000L, ulb =
0x80000000L;
signed short ssc = 0xffffffff, ssa = 0x80000000, ssb = 0x80000000;
/* the above line leads to truncation in my implementation, shorts
not being 32 bits */
signed long slc = 0xffffffffL, sla = 0x80000000L, slb = 0x80000000L;
printf("[Output for this implementation]\n");
printf("%d < (%d - %d)? %s\n",
ssc, ssa, ssb, (ssc < (ssa - ssb)) ? "yes" : "no");
printf("%ld < (%ld - %ld)? %s\n",
slc, sla, slb, (slc < (sla - slb)) ? "yes" : "no");
printf("%u < (%u - %u) or %x < (%x - %x)? %s\n",
usc, usa, usb,
usc, usa, usb, (usc < (usa - usb)) ? "yes" : "no");
printf("%lu < (%lu - %lu) or %lx < (%lx - %lx)? %s\n\n",
ulc, ula, ulb,
ulc, ula, ulb, (ulc < (ula - ulb)) ? "yes" : "no");

usc = 0xffff;
usa = 0x8000;
usb = 0x8000;
ulc = 0xffffL;
ula = 0x8000L;
ulb = 0x8000L;
ssc = 0xffff;
ssa = 0x8000;
ssb = 0x8000;
/* the above lines lead to truncation in my implementation, shorts
not being 32 bits */
slc = 0xffffL;
sla = 0x8000L;
slb = 0x8000L;
printf("%d < (%d - %d)? %s\n",
ssc, ssa, ssb, (ssc < (ssa - ssb)) ? "yes" : "no");
printf("%ld < (%ld - %ld)? %s\n",
slc, sla, slb, (slc < (sla - slb)) ? "yes" : "no");
printf("%u < (%u - %u) or %x < (%x - %x)? %s\n",
usc, usa, usb,
usc, usa, usb, (usc < (usa - usb)) ? "yes" : "no");
printf("%lu < (%lu - %lu) or %lx < (%lx - %lx)? %s\n\n",
ulc, ula, ulb,
ulc, ula, ulb, (ulc < (ula - ulb)) ? "yes" : "no");
return 0;
}


[Output for this implementation]
-1 < (0 - 0)? yes
-1 < (-2147483648 - -2147483648)? yes
65535 < (0 - 0) or ffff < (0 - 0)? no
4294967295 < (2147483648 - 2147483648) or ffffffff < (80000000 -
80000000)? no

-1 < (-32768 - -32768)? yes
65535 < (32768 - 32768)? no
65535 < (32768 - 32768) or ffff < (8000 - 8000)? no
65535 < (32768 - 32768) or ffff < (8000 - 8000)? no
 
G

ganeshk

Eric,
Thanks a lot! I solved the problem but I still have a question.
For example, `ffffffff' is *not* -1; it is (if there's a `0x' at the beginning)
4294967295.

The problem was this:
As mentioned before, I was getting the value of 'a' from a #define. (c
and b are ok since they are got from input and are signed numbers)

#define a 0x80000000
assigned not -2147483648 but some other big positive value to 'a'.

Now, I removed the #define and put this as a statement inside my
function and it works.

But lint gives a warning saying that "initializer is out of range:
0x80000000"

How can I fix it?

Thanks
Bruce
 
G

ganeshk

Thanks a lot! I solved the problem but I still have a question.
For example, `ffffffff' is *not* -1; it is (if there's a `0x' at the beginning)
4294967295.

The problem was this:
As mentioned before, I was getting the value of 'a' from a #define. (c
and b are ok since they are got from input and are signed numbers)

#define a 0x80000000
assigned not -2147483648 but some other big positive value to 'a'.

Now, I removed the #define and put this as a statement inside my
function and it works.

But lint gives a warning saying that "initializer is out of range:
0x80000000"

How can I fix it?

Thanks
Bruce
 
B

bruce.james.lee

Thanks for the hints. I solved the problem but now I have another
problem!
In
printf("%d", c < (a - b));
'a' is got from #define as I mentioned earlier, now all that is in the
#define is treated as unsigned! So
#define a 0x800000000
assigns not -2147483648 but some big positive value. And this caused
problems in my calculation with signed numbers.
I fixed this by saying
int a = -2147483648 ; inside my function.
but C gives a warningsaying it is out of range. I searched for this new
problem, know why it occurs, but what would be the best solution?
 
B

bruce.james.lee

Eric,
The reason I did not heed your suggestion is simple, the problem got
solved but turned into another. which is just

"int a = 0x80000000;"
gives a warning since a is -2147483648 which is split as an operator
and a positive number by C.

How to remove this warning? (a = -2147483647 - 1 looks dirty)


Eric said:
Eric,
Thanks a lot! I solved the problem but I still have a question.
[...]

... and you have failed to pay any heed to a crucial
part of my earlier response, to wit
[...] please post an *actual* *complete* *minimal* example
of the code that baffles you. [...]
How can I fix it?

My crystal ball says your error is on line 42.
 
A

A. Sinan Unur

(e-mail address removed) wrote in @f14g2000cwb.googlegroups.com:

Eric said:
[...] please post an *actual* *complete* *minimal* example
of the code that baffles you. [...]
....
... and you have failed to pay any heed to a crucial
part of my earlier response, to wit
Eric,
The reason I did not heed your suggestion is simple, the problem got
solved but turned into another. which is just

How does that eliminate the importance of posting that satisfies the the
three important criteria listed above???
"int a = 0x80000000;"

#include <stdio.h>
#include <limits.h>

int main(void) {
printf("The maximum possible value for an int is: %d\n", INT_MAX);
printf("The minimum possible value for an int is: %d\n", INT_MIN);
return 0;
}

The value you are assigning to a, 0x80000000 is an unsigned literal
whose value does not fit in a signed int.

If you want to assign -1 to a, then you should do exactly that:

int a = -1;

Now, that is not so hard, is it?

Sinan
 
B

bruce.james.lee

Sinan,
I dont think u got the problem. The value I want in 'a' is -2147483648,
not -1.

int a = -2147483648;
will generate a warning.

int a = 0x80000000;
will also generate a warning.

how to eliminate the warning, is my query.

A. Sinan Unur said:
(e-mail address removed) wrote in @f14g2000cwb.googlegroups.com:

Eric said:
[...] please post an *actual* *complete* *minimal* example
of the code that baffles you. [...] ...
... and you have failed to pay any heed to a crucial
part of my earlier response, to wit
Eric,
The reason I did not heed your suggestion is simple, the problem got
solved but turned into another. which is just

How does that eliminate the importance of posting that satisfies the the
three important criteria listed above???
"int a = 0x80000000;"

#include <stdio.h>
#include <limits.h>

int main(void) {
printf("The maximum possible value for an int is: %d\n", INT_MAX);
printf("The minimum possible value for an int is: %d\n", INT_MIN);
return 0;
}

The value you are assigning to a, 0x80000000 is an unsigned literal
whose value does not fit in a signed int.

If you want to assign -1 to a, then you should do exactly that:

int a = -1;

Now, that is not so hard, is it?

Sinan
 
M

Mark McIntyre

As mentioned before, I was getting the value of 'a' from a #define. (c
and b are ok since they are got from input and are signed numbers)

#define a 0x80000000

this defines a macro 'a' of size large enough to hold 0x80000000. What
size is large enough to hold that on your platform?
assigned not -2147483648 but some other big positive value to 'a'.

yes, because it /is/ a large positive value. Why do you think its
negative?

But lint gives a warning saying that "initializer is out of range:
0x80000000"

(of using a variable instead of a macro)
How can I fix it?

initialise a variable that is big enough. What type did you use for a,
is it large enough to hold 0x80000000 ?
 
M

Mark McIntyre

On 3 Apr 2005 15:34:44 -0700, in comp.lang.c ,
Eric,
The reason I did not heed your suggestion is simple, the problem got
solved but turned into another.

Hmm. Because you have a different problem, which is equally impossible
to solve properly without some actual code, you decided to ignore
Eric's request to post some code? Hmm.
which is just

"int a = 0x80000000;"
gives a warning since a is -2147483648 which is split as an operator
and a positive number by C.

What makes you think this is 'split as an operator and positive
number' ? Its a BAD idea to guess whats going on. Have a harder
think.
How to remove this warning? (a = -2147483647 - 1 looks dirty)

use the right size variable?
 
B

bruce.james.lee

Mark,

Its not a guess, I did enough googling and searched in google groups
before asking here, and most said it is a 'split as an operator and
positive
number'. And it made sense, so I think it is right.

Bruce

Mark said:
On 3 Apr 2005 15:34:44 -0700, in comp.lang.c ,


Hmm. Because you have a different problem, which is equally impossible
to solve properly without some actual code, you decided to ignore
Eric's request to post some code? Hmm.


What makes you think this is 'split as an operator and positive
number' ? Its a BAD idea to guess whats going on. Have a harder
think.


use the right size variable?
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption
=----
 
D

dot

Sinan,
I dont think u got the problem. The value I want in 'a' is -2147483648,
not -1.

int a = -2147483648;
will generate a warning.

int a = 0x80000000;
will also generate a warning.

Ummm... are integers 32 bits in the compiler you're using?

Also look in your headers, if you have a limits.h header, it should provide
a constant INT_MIN which will be the lowest legal value for your compiler.
Use it instead of trying to define a new one...
 
B

bruce.james.lee

Yes, they are 32 bits. So, I calculated -2^31 as the minimum possible
number.

I just saw the header file you mentioned, it reads

#define INT32_MIN (-2147483647-1)

I will do this as well.

Thanks everyone!
 
J

joshc

Thanks for the hints. I solved the problem but now I have another
problem!
In
printf("%d", c < (a - b));
'a' is got from #define as I mentioned earlier, now all that is in the
#define is treated as unsigned! So

I guess you are ignoring everything Eric has said previously?!?! If you
had read what he posted then this would not have been a surprise
because as he mentioned you are thinking about the representation, not
the VALUE.
 
A

A. Sinan Unur

(e-mail address removed) wrote in @f14g2000cwb.googlegroups.com:

Also look in your headers, if you have a limits.h header, it should
provide a constant INT_MIN which will be the lowest legal value for
your compiler. Use it instead of trying to define a new one...

Yes, they are 32 bits. So, I calculated -2^31 as the minimum possible
number.

I just saw the header file you mentioned, it reads

#define INT32_MIN (-2147483647-1)

The recommendation was to check the value of INT_MIN, not INT32_MIN.
INT_MIN should be in limits.h.

Sinan
 
P

Peter Nilsson


[Please preserve the relevant context of what you're
replying to.]
There is no INT_MIN defined in my limits.h

Then either your implementation is non-conforming, or you
haven't invoked the options needed for conformance.

If the former, then you should consult a newsgroup
specific to your development tools.

That said, you can always define it yourself...

#define MINUS_0x80000000 (-0x7FFFFFFF-1)

int32_t x = MINUS_0x80000000;
 
B

bruce.james.lee

Peter,
I did define it myself
#define MINUS_0x80000000 (-0x7FFFFFFF-1)

and I directly used it in my code without doing the assignment you
mentioned (int32_t x = MINUS_0x80000000;).

That is working.

Thanks
Bruce

Peter said:

[Please preserve the relevant context of what you're
replying to.]
There is no INT_MIN defined in my limits.h

Then either your implementation is non-conforming, or you
haven't invoked the options needed for conformance.

If the former, then you should consult a newsgroup
specific to your development tools.

That said, you can always define it yourself...

#define MINUS_0x80000000 (-0x7FFFFFFF-1)

int32_t x = MINUS_0x80000000;
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top