INT_MIN as decimal

J

Jordan Abel

Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? Or is it the unsigned
int literal 32768 with the unary minus operator applied to it, resulting
in the value of the expression being an unsigned int 32768, which can
then trap when being assigned to a signed int type [It appears to me
that the minus sign is not actually part of the literal, since it's not
part of a number token]
 
L

Lew Pitcher

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jordan said:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative?

Yes. In a 16bit classical two's-complement number, the values can range
from -32768 to 32767.

[snip]



- --

Lew Pitcher, IT Specialist, Corporate Technology Solutions,
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed here are my own, not my employer's)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEDySNagVFX4UWr64RAkdZAJ4/S3hRCcOhmlQUnXDoxxJQpWBy8ACgy0zI
KVrkW7epRRwQvX2L/wtpQ8k=
=4i2Y
-----END PGP SIGNATURE-----
 
B

Ben Pfaff

Jordan Abel said:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? [...]

Yes, but it has type "long int". If you want an "int" with the
same value, you can write -32767 - 1.
 
B

Ben Pfaff

Lew Pitcher said:
Yes. In a 16bit classical two's-complement number, the values
can range from -32768 to 32767.

True, but deceptive--see my article elsewhere in the thread.
 
G

Guest

Jordan said:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? Or is it the unsigned
int literal 32768 with the unary minus operator applied to it, resulting
in the value of the expression being an unsigned int 32768, which can
then trap when being assigned to a signed int type [It appears to me
that the minus sign is not actually part of the literal, since it's not
part of a number token]

In C99, 32768 will be of type long, so -32768 will have the expected
value.
 
B

Ben Pfaff

Harald van DD3k said:
Jordan said:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? [...]

In C99, 32768 will be of type long, so -32768 will have the expected
value.

I don't think the situation is different in C90.
 
R

Robin Haigh

Jordan Abel said:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? Or is it the unsigned
int literal 32768 with the unary minus operator applied to it, resulting
in the value of the expression being an unsigned int 32768, which can
then trap when being assigned to a signed int type [It appears to me
that the minus sign is not actually part of the literal, since it's not
part of a number token]

As I read it, a decimal, rather than hex, constant that won't fit into an
int is a long. So it's a unary minus applied to a long, yielding a long.
Life is full of surprises today.

Different answer for 32-bit ints, if long is also 32 bits. Then it's long
long in C99. In C89, unary minus applied to 2^31 as unsigned long... er,
hmm, I see the problem
 
G

Guest

Ben said:
Harald van DD3k said:
Jordan said:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? [...]

In C99, 32768 will be of type long, so -32768 will have the expected
value.

I don't think the situation is different in C90.

I don't have C90 to check, but my compiler (GCC) does think it's
different, and it treats -2147483648 as positive unsigned in C90 mode,
and as negative signed in C99 mode.
 
B

Ben Pfaff

Harald van DD3k said:
Ben said:
Harald van DD3k said:
Jordan Abel wrote:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? [...]

In C99, 32768 will be of type long, so -32768 will have the expected
value.

I don't think the situation is different in C90.

I don't have C90 to check, but my compiler (GCC) does think it's
different, and it treats -2147483648 as positive unsigned in C90 mode,
and as negative signed in C99 mode.

In C90 mode, does it recognize long long integer constants? If
not, that would explain the discrepancy, I think.

The OP's situation is different, because `int' and `long' are
both in C90.
 
G

Guest

Ben said:
Harald van DD3k said:
Ben said:
Jordan Abel wrote:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? [...]

In C99, 32768 will be of type long, so -32768 will have the expected
value.

I don't think the situation is different in C90.

I don't have C90 to check, but my compiler (GCC) does think it's
different, and it treats -2147483648 as positive unsigned in C90 mode,
and as negative signed in C99 mode.

In C90 mode, does it recognize long long integer constants? If
not, that would explain the discrepancy, I think.

The OP's situation is different, because `int' and `long' are
both in C90.

In C90 mode, it fully supports long long, constants and variables
(though with an optional warning). However, you are right. In C89,
according to the C99 rationale, 2147583648 is too large for int, too
large for long, not too large for unsigned long, so that is its type.
unsigned int is not considered, only unsigned long is. Thanks. I am not
entirely sure though, because a little bit later I read this:

QUIET CHANGE IN C89
Unsuffixed integer constants may have different types. In K&R,
unsuffixed decimal constants greater than INT_MAX, and unsuffixed octal
or hexadecimal constants greater than UINT_MAX are of type long.

So it basically says that in C89, unsuffixed decimal constants greater
than INT_MAX, such as 32768 in the original question, are not of type
long. And I can't think of any type other than unsigned int that would
be appropriate for it.
 
C

Chris Torek

Yes. In a 16bit classical two's-complement number, the values can range
from -32768 to 32767.

That range is correct; but I think you missed Jordan Abel's point:
the token sequence you get in C source code is not:

-32768

i.e., one token, but rather:

-
32768

i.e., two separate tokens. The first token is the unary minus
operator. The second token is an integer constant, expressed in
decimal. The rules for typing integer constants say that we have
to look at the mathematical value, and see what type(s) can
hold them. If int uses the usual 16 bit two's-complement,
INT_MAX is 32767, so 32768 "means" the same thing as 32768U:
it has type "unsigned int". So we have, in effect:

-(32768U)

which, using 16-bit unsigned int arithmetic, is +32768.

Hence, if you have a <limits.h> file you can read, and you look at
it, you will find that INT_MIN is typically defined as:

#define INT_MIN (-32767 - 1)

or:

#define INT_MIN (-2147483647 - 1)

Without doing some kind of arithmetic, you get the wrong type!
 
C

Chris Torek

... If int uses the usual 16 bit two's-complement,
INT_MAX is 32767, so 32768 "means" the same thing as 32768U:
it has type "unsigned int".

This is wrong; it has type "long" (which goes to at least +217483647).
So we have, in effect:

-(32768U)

This should be -(32768L).
Hence, if you have a <limits.h> file you can read, and you look at
it, you will find that INT_MIN is typically defined as:

#define INT_MIN (-32767 - 1)

or:

#define INT_MIN (-2147483647 - 1)

Without doing some kind of arithmetic, you get the wrong type!

This is still right, though.

Also, C99 changes what -2147483648 means with 32-bit "int" since C99
has "long long".
 
C

CBFalconer

Ben said:
Jordan Abel said:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? [...]

Yes, but it has type "long int". If you want an "int" with the
same value, you can write -32767 - 1.

Or you can write "INT_MIN", which probably expands to your
expression after #include <limits.h>. You already know this, but
the reader may not.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
P

pete

Jordan said:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? Or is it the unsigned
int literal 32768 with the unary minus operator applied to it,
resulting
in the value of the expression being an unsigned int 32768, which can
then trap when being assigned to a signed int type [It appears to me
that the minus sign is not actually part of the literal,
since it's not
part of a number token]

The order is {int, long, long unsigned}
for choosing the type of an integer constant
according to value ranges.
 
K

Keith Thompson

pete said:
Jordan said:
Say int is a 16-bit twos-complement type.

Is the expression (-32768) actually negative? Or is it the unsigned
int literal 32768 with the unary minus operator applied to it,
resulting
in the value of the expression being an unsigned int 32768, which can
then trap when being assigned to a signed int type [It appears to me
that the minus sign is not actually part of the literal,
since it's not
part of a number token]

The order is {int, long, long unsigned}
for choosing the type of an integer constant
according to value ranges.

That's true for C90. In C99, the order is int, long int, long long
int. (That's for unsuffixed decimal constants.)

Since long long int is required to be at least 64 bits, presumably
it's not as important to allow a decimal literal to be treated as
unsigned; a programmer knows enough to write a correct 19-digit
decimal literal is going to know enough to use a suffix, or to use
hexadecimal or octal.
 
P

Peter Nilsson

Jordan said:
Say int is a 16-bit twos-complement type.
Is the expression (-32768) actually negative?

Yes, but the expression has type long, not int.
Or is it the unsigned int literal 32768 with the unary minus operator
applied to it, resulting in the value of the expression being an
unsigned int 32768, which can then trap when being assigned to a
signed int type

It's a long literal with the unary minus operator applied.

Since -32768L _is_ within the range of your signed int, it won't trap
on
a corresponding C90 or C99 implementation.

Note that only C99 has the potential for implementation defined signals
on
assignment to a signed integer of a value not in range of that integer.
For
C90 the conversion is always implementation defined (i.e. unspecified
but
legal).

Had you written (-0x8000) the expression would yield a positive
unsigned
value and you might have a problem under C99.
[It appears to me that the minus sign is not actually
part of the literal, since it's not part of a number token]

Correct. All integer constants are non-negative. All floating point
constants are non-negative too. Adding an unary - (or unary +)
makes it a constant expression.
 

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,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top