'Why can't a hexadecimal integer constant be negative?

This table shows type is the first type in which the value can fit. Examining 0xFFFFFFF0 with gdb shows it to be an unsigned type:

(gdb) ptype 0xFFFFFFF0
type = unsigned int

But 0xFFFFFFF0 is -16 when interpreted as a signed integer so why can't it fit in the int type? Doing the same with a decimal input shows the desired type:

ptype -16
type = int

I also wanted to ask about this sentence in the same link above:

There are no negative integer constants. Expressions such as -1 apply the unary minus operator to the value represented by the constant, which may involve implicit type conversions.

So -1 = 0 -1 = -1, AKA a negative integer? I don't understand this sentence.



Solution 1:[1]

It has nothing to do with the constant being hex -- it has solely to do with the value of the constant and how many bits it.

The rules for typing of constant literals (without type suffixes) are pretty simple. It simply checks to see if the value is in range for various signed and unsigned integer types, starting with int and going to progressively larger types, until it finds one that fits. It tries the signed type of a given size before the unsigned type of that size.

The same thing happens if you use a decimal int:

(gdb) ptype 4294967280
type = unsigned int

here 4294967280 is the deciaml value of 0xfffffff0. Since this value is out of range for int but in range for unsigned int, that's what it is. Try a number with one more digit (hex or decimal) and you'll get long long as it is out of range for unsigned int.

Using a negative number, you'll generally get a signed type:

(gdb) ptype -0x10
type = int

however, the - isn't really part of the constant, it is an operator applied to the literal and does not affect its type. So you see

(gdb) p 0xfffffff0
$1 = 4294967280
(gdb) p -0xfffffff0
$2 = 16
(gdb) ptype -0xfffffff0
type = unsigned int
(gdb) ptype 4294967280
type = unsigned int
(gdb) p -4294967280
$3 = 16
(gdb) ptype -4294967280
type = unsigned int

Note the last one -- a decimal constant that is too big for int (but in range for unsigned) giving a suprising output. This despite the fact that the C spec seems to unambiguously state that decimal constants will always be signed, rather than unsigned, regardless of the value.

with bigger numbers

(gdb) p 0xffffffff0
$4 = 68719476720
(gdb) ptype 0xffffffff0
type = long long
(gdb) p -0xffffffff0
$5 = -68719476720

Solution 2:[2]

Shorten answers

Why can't a hexadecimal integer constant be negative?

In C, all integer constants are non-negative (0 or more) as that is how the language is defined.

But 0xFFFFFFF0 is -16 when interpreted as a signed integer so why can't it fit in the int type?

The first type 0xFFFFFFF0 fits in is unsigned, not int as is greater than INT_MAX.

Doing the same with a decimal input shows the desired type: ptype -16 type = int

16 fits in an int, so it is an int. After the type is determined, the negating of that is well defined, so the value of the expression is -16.

So -1 = 0 -1 = -1, AKA a negative integer? I don't understand this sentence.

Consider -1 and 0 - 1 employ the int constants 0 and 1 and are expressions both with a value of -1 and type of int.

Solution 3:[3]

But 0xFFFFFFF0 is -16 when interpreted as a signed integer so why can't it fit in the int type?

When you say "interpreted as", you are failing to distinguish between an external representation of a number and an internal one. I presume that the fact that the constant in question is expressed in hexadecimal is contributing to this error. I doubt you would suggest that 4294967280 should be interpreted as -16 (decimal), yet that is exactly analogous to what you are suggesting for the hexadecimal version.

The fact is that hexadecimal integer constants are not to be interpreted as bit patterns for this purpose. They are hexadecimal representations of numbers. They are implicitly positive, there being no mechanism provided in the lexical form of an integer constant to express a negative number. (Negative numbers can be formed as expressions involving integer constants and the unary - operator.)

Among other things, this supports portability, as C does not specify the exact sizes of the various integer types, and implementations do vary in practice. C also allows three different choices for the representation of negative integers, though these days implementatoins pretty consistently use twos complement format. A given integer constant, whether expressed in octal, decimal, or hexadecimal, will be interpreted as the same numeric value by every C implementation (though there may be some that have no data type that can represent that value).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 chux - Reinstate Monica
Solution 3