Home > OS >  Why can't a hexadecimal integer constant be negative?
Why can't a hexadecimal integer constant be negative?

Time:03-02

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.

CodePudding user response:

There are no negative integer constants in C.

The grammar for integer constants is:

  • A decimal constant is a sequence of decimal digits not starting with 0 and with an optional suffix (u and/or l or ll in either order with any cases [uppercase or lowercase]).
  • An octal constant is a sequence of octal digits starting with 0 and an optional suffix.
  • A hexadecimal constant is 0x followed by a sequence of hexadecimal digits, with any cases.

None of those have a minus sign. All integers constants in C are numerals with nonnegative values. Where a minus sign appears with a constant in C code, as in -34, it is two separate tokens: a unary negation operator followed by a constant.

The goal of selecting a type for a constant is to select a type that can represent its value. As a hexadecimal numeral, the value of FFFFFFF016 is 4,294,967,280. If 0xFFFFFFF0 were made a 32-bit int, the value of that int would be −16 in two’s complement or some other values in one’s complement or sign-and-magnitude. It would not be 4,294,967,280. So a 32-bit int cannot represent the value of this numeral, so the compiler does not use a 32-bit int for the type.

There are also no negative floating-point constants. Enumeration constants and character constants can be negative in some circumstances.

CodePudding user response:

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

CodePudding user response:

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.

CodePudding user response:

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).

  • Related