Integer subtraction problem, help!

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

Mark McIntyre

On 3 Apr 2005 15:54:51 -0700, in comp.lang.c ,
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.

You fail to tell us the error (please re-read Eric's advice, and post
your /actual/ code and /actual/ error messages) , but its probably
something like

warning C4146: unary minus operator applied to unsigned type, result
still unsigned

This problem has already been answered. USE A TYPE THAT IS LARGE
ENOUGH. You can't fit that number into an int (or even into a long,
probably) on your computer.
 
K

Keith Thompson

There is no INT_MIN defined in my limits.h

Unlikely.

Did you look for the string "INT_MIN" in your limits.h file (perhaps
in /usr/include), or did you try to use it in a C program?

If the limits.h file itself doesn't define INT_MIN, it's probably
defined in another system-specific header file that limits.h includes.

Try this program:

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

int main()
{
printf("INT_MIN = %d\n", INT_MIN);
return 0;
}

If it compiles and prints a value (most likely -2147483648, but
possibly -32768), then <limit.h> defines INT_MIN properly. Don't
worry about what's in the file. If the program doesn't compile,
something in your system is configured incorrectly.

The standard requires an implementation to provide a <limits.h>
header. It doesn't require it to be a file, and if it is a file it
doesn't have to be legible. It just has to work.
 
M

Mark McIntyre

On 3 Apr 2005 16:09:49 -0700, in comp.lang.c ,
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.

Okay, I see what it means. Yes, in that sense it is treated thus.

There's no way to stop it, this is how the C parser works, the "-" is
a unary operator and operates on its operand, in this case 2147483648.
Since that won't fit into an int, you can't use it.

But now we're back to what I said - you're trying to fit a quart into
a pint pot. Choose a variable thats the right size.

 
K

Keith Thompson

Mark McIntyre said:
On 3 Apr 2005 16:09:49 -0700, in comp.lang.c ,

What exactly is "it"? What is "split as an operator and positive number"?

A value stored in a variable is not split in this way; it's just a
value. I think what you're referring to is how to represent the value
as a C expression.
Okay, I see what it means. Yes, in that sense it is treated thus.

There's no way to stop it, this is how the C parser works, the "-" is
a unary operator and operates on its operand, in this case 2147483648.
Since that won't fit into an int, you can't use it.

But now we're back to what I said - you're trying to fit a quart into
a pint pot. Choose a variable thats the right size.

In the following I'll assume that "int" is a 32-bit 2's-complement
type with no padding bits or trap repsentations. When I use the
phrase "numeric value", I'm talking about a mathematical integer
value, not a C expression or a value of any C type. Finally, I'll use
the term "integer literal" where the standard talks about "integer
constants", just to avoid confusion with the unrelated "const"
feature.

I think the point is that the OP wants to store the numeric value
-2147483648 in an int. Since this happens to be the value of INT_MIN,
it should be possible. Unfortunately, it's not as easy as you might
expect.

C has no negative integer literals, only non-negative ones. Something
like -42 is not a literal, it's a literal with a unary "-" operator
applied to it. In many contexts, this difference doesn't matter, but
you've found one where it does.

If -2147483648 were treated as a negative literal, then this:

int a = -2147483648;

would be ok. Instead, 2147483648 is a literal, and it can't be
represented as an int. Let's assume type "long int" is 64 bits,
making 2147483648 a literal of type long int with the obvious value.
Applying the "-" to this value yields a long int with the numeric
value -2147483648. Using this to initialize an int causes an implicit
conversion, and stores the expected value in a.

But in a C90 implementation, the longest integer might be only 32
bits. This means that 2147483648 is not a value of *any* integer
type. Attempting to use it in a program results in a warning.

The declaration

int a = -2147483648;

will still *probably* do what you expect, but there's no guarantee,
and you can expect the compiler to warn you that you're doing
something questionable.

An easy workaround is to use a slightly more complicated expression:

int a = -2147483647-1;

Both literals (with positive values) are within the range of type int,
and none of the intermediate expressions cause an overflow.

Out of the 4294967296 distinct values of a 32-bit 2's-complement
integer type, 42949672965 can be easily represented in C by either a
single integer literal, or by an integer literal with a unary "-"
operator; only one value cannot be represented this way. This is
arguably a hole in the language, but given that there's an easy
workaround, it's probably not worth adding a special-case feature to
correct it.

Some more things to keep in mind:

The standard doesn't guarantee that int is 32 bits; the minimum
guaranteed range is only -32767 .. +32767.

If you're assuming a 32-bit 2's-complement representation for int, you
can just use INT_MIN, defined in <limits.h>.
 
P

pete

Keith said:
Unlikely.

Did you look for the string "INT_MIN" in your limits.h file (perhaps
in /usr/include), or did you try to use it in a C program?

If the limits.h file itself doesn't define INT_MIN, it's probably
defined in another system-specific header file that limits.h includes.

Try this program:

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

int main()
{
printf("INT_MIN = %d\n", INT_MIN);
return 0;
}

or this one:

/* BEGIN new.c */

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

#define str(s) # s
#define xstr(s) str(s)

int main(void)
{
puts("INT_MIN = " xstr(INT_MIN));
return 0;
}

/* END new.c */
 
J

Joe Wright

pete said:
or this one:

/* BEGIN new.c */

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

#define str(s) # s
#define xstr(s) str(s)

int main(void)
{
puts("INT_MIN = " xstr(INT_MIN));
return 0;
}

/* END new.c */
Neat. This yields ..

INT_MIN = (-2147483647-1)

... at my house. I'm gonna start looking at that # and ## stuff.

Thanks pete.
 
P

pete

Joe said:
Neat. This yields ..

INT_MIN = (-2147483647-1)

.. at my house. I'm gonna start looking at that # and ## stuff.

Thanks pete.

I'm glad you liked it.
It comes in handy if you're implementing something like this:

#define LENGTH 3
#define str(x) # x
#define xstr(x) str(x)

int rc;
char array[LENGTH + 1];

rc = scanf("%" xstr(LENGTH) "[^\n]%*[^\n]", array);
if (!feof(stdin)) {
getchar();
}

rc is 1 if any characters are read before the newline.
The text line is converted to a string in the array.
rc is 0 if the line consists of a newline character only.
Nothing is converted.
rc is EOF if you use fscanf instead of scanf
and read the end of a text file.

I think that converting strings to lines and lines to strings,
is a good way for a program to interact with a text file.
I used lower case xstr for the macro
because I copied it from the standard.
 

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
474,161
Messages
2,570,892
Members
47,428
Latest member
RosalieQui

Latest Threads

Top