initializing int to a number bigger than INT_MAX

V

vikky

hi all,
Out of sheer curosity, I decided to initialize an integer with a number
bigger than INT_MAX, however I still am not able to justify its output.
Here is the program :

#include<stdio.h>

int main(void)
{
int t=0xFFFFFFFFFFFFFFFFDABC;
printf("t is : %x\n",t);
getchar();
return 0;
}
I ran this program using Dev-C++ in Windows on x86( gcc.exe
"C:\Untitled.c" -o "C:\Untitled.exe" -Wall -pg -g3
-I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib" -lgmon -pg -g3)

The output was
t is : ffffdabc

What is happening in here?
And even if I write
int t=0xFFFCFDFAFFFFFFFFDABC;
it is giving the same output. Infact even if i increase any hex digit
at beginning(like int t=0xFFAAAAFFFFFFFFFFFFFFDABC;) it is giving the
same output.

I guess its some kind of truncation going on .. but then why is it
ignoring MSBs ? I am also guessing this behaviour is compiler dependent
- am i correct?
 
J

jeff_hann

hi all,
Out of sheer curosity, I decided to initialize an integer with a number
bigger than INT_MAX, however I still am not able to justify its output.
Here is the program :

#include<stdio.h>

int main(void)
{
int t=0xFFFFFFFFFFFFFFFFDABC;
printf("t is : %x\n",t);
getchar();
return 0;
}
I ran this program using Dev-C++ in Windows on x86( gcc.exe
"C:\Untitled.c" -o "C:\Untitled.exe" -Wall -pg -g3
-I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib" -lgmon -pg -g3)

The output was
t is : ffffdabc

What is happening in here?
And even if I write
int t=0xFFFCFDFAFFFFFFFFDABC;
it is giving the same output. Infact even if i increase any hex digit
at beginning(like int t=0xFFAAAAFFFFFFFFFFFFFFDABC;) it is giving the
same output.

I guess its some kind of truncation going on .. but then why is it
ignoring MSBs ? I am also guessing this behaviour is compiler dependent
- am i correct?
 
J

jeff_hann

hi all,
Out of sheer curosity, I decided to initialize an integer with a number
bigger than INT_MAX, however I still am not able to justify its output.
Here is the program :

#include<stdio.h>

int main(void)
{
int t=0xFFFFFFFFFFFFFFFFDABC;
printf("t is : %x\n",t);
getchar();
return 0;
}
I ran this program using Dev-C++ in Windows on x86( gcc.exe
"C:\Untitled.c" -o "C:\Untitled.exe" -Wall -pg -g3
-I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib" -lgmon -pg -g3)

The output was
t is : ffffdabc

What is happening in here?
And even if I write
int t=0xFFFCFDFAFFFFFFFFDABC;
it is giving the same output. Infact even if i increase any hex digit
at beginning(like int t=0xFFAAAAFFFFFFFFFFFFFFDABC;) it is giving the
same output.

I guess its some kind of truncation going on .. but then why is it
ignoring MSBs ? I am also guessing this behaviour is compiler dependent
- am i correct?

Hi,
First of all,I think it is[like you said] compiler/platform -
dependent,so,it's
a little OT.Second,why 'getchar()'?And third,this is,in my humble
opinion,clearly undefined.
 
M

Michael Coyne

hi all,
Out of sheer curosity, I decided to initialize an integer with a number
bigger than INT_MAX, however I still am not able to justify its output.
Here is the program :

int t=0xFFFFFFFFFFFFFFFFDABC;

First of all, this is in fact *smaller* than INT_MAX. What you've
written is a negative number, as you're using a signed int. All the
extra leading Fs, above and beyond the 32-bit limit of your architecture,
in binary terms, are leading ones, which can "safely" be "dropped" and
still yield the same 2s-complement number in a "lower int-sized" machine,
assuming the meaningful bits of the number are small enough to fit.

Hmmm, I didn't explain that very well, but...

I'm surprised you would know of the existence of INT_MAX, yet
don't seem to follow what it means.

INT...
MAX...

It's the maximum size int you can declare.

I suspect that on your hardware, INT_MAX is 0x7FFF FFFF, or 2,147,483,647.

INT_MIN will be declared as -INT_MAX-1 or -2,147,483,648.

So by trying to enter more than 32 bits into your declared int, it's
getting truncated to the lowest 32 bits, 0xFFFFDABC, or -9540.

Note that 0xFFFF FFFF is the "largest" hexadecimal value that can be held
by an int on your architecture. Note also that for a signed int, this is
actually -1.
I guess its some kind of truncation going on .. but then why is it
ignoring MSBs ? I am also guessing this behaviour is compiler dependent
- am i correct?

In so far as INT_MAX and INT_MIN will change from compiler to compiler and
architecture to architecture, yes.


Michael
 
K

Keith Thompson

hi all,
Out of sheer curosity, I decided to initialize an integer with a number
bigger than INT_MAX, however I still am not able to justify its output.
Here is the program :

#include<stdio.h>

int main(void)
{
int t=0xFFFFFFFFFFFFFFFFDABC;
printf("t is : %x\n",t);
getchar();
return 0;
} [snip]
The output was
t is : ffffdabc
[snip]

Strictly speaking, the "%x" specifier expects an unsigned int. You
can almost certainly get away with passing an int, but I still prefer
to use an explicit cast (one of the few cases where casts are useful):

printf("t is : %x\n", (unsigned)t);

The literal 0xFFFFFFFFFFFFFFFFDABC requires 80 bits, which is probably
(but not certainly) larger than any integer type.

An unsuffixed hexadecimal integer constant's type is the first type
from this list:

int
unsigned int
long int
unsigned long int
long long int (C99 only)
unsigned long long int (C99 only)

in which the value can be represented. If it can't be represented in
any of those types, it may have an extended integer type (if the
implementation has extended integer types; I don't know of any that
do). If there is no type that can represent the value, the standard
doesn't say what its type is; I believe this means it invokes
undefined behavior by omission (i.e., the behavior is undefined not
because the standard says so, but because it fails to define the
behavior).

I'd be happier if the standard said something explicit about integer
constants that can't be represented in any type.

On the other hand, suppose you use a literal that fits in some integer
type, but not in int. For example, assuming 32-bit int and long, and
64-bit long long:

int t = 0xFFFFFFFFFFFFDABC; /* 64 bits */

the constant is of type unsigned long long. The value is implicitly
converted to type int before being used to initialize t. An
overflowing conversion to a signed integer type doesn't invoke
undefined behavior; it merely yields an implementation-defined result
or raises an implementation-defined signal. (In C90, it yields an
undefined result; there's no mention of raising a signal.)

Having said all that, on every implementation I know of a conversion
from a larger to a smaller integer type simply discards the high-order
bits. You shouldn't depend on this behavior in portable code.
 
E

Eric Sosman

Michael said:
First of all, this is in fact *smaller* than INT_MAX. What you've
written is a negative number, as you're using a signed int. All the
extra leading Fs, above and beyond the 32-bit limit of your architecture,
in binary terms, are leading ones, which can "safely" be "dropped" and
still yield the same 2s-complement number in a "lower int-sized" machine,
assuming the meaningful bits of the number are small enough to fit.

Hmmm, I didn't explain that very well, but...

No, indeed: Much of what you wrote was incorrect.

To begin with, the hexadecimal constant is a large
*positive* number. In fact, all numeric[*] constants in C
are non-negative. The problems here are (1) that the big
hex constant may be too large for any integral data type
supported by the implementation, and (2) even if that's
not the case, it may be bigger than INT_MAX.

Case 1 may apply even though the compiler didn't
complain; I can't find anything in the Standard that seems
to require a diagnostic for out-of-range constants. If
case 1 applies, we really can't tell for sure what happened,
but it looks like the compiler may have mangled the value
(along the lines you describe, and that part of your answer
was correct -- for two's complement machines, anyhow).

If it's case 2, initialization is "as if" by conversion
of the very large value to `int'. Converting an out-of-range
value to `int' produces an implementation-defined result (or
raises an implementation-defined signal). On two's complement
machines it is likely that the implementation-defined result
will be "chopped" in the way you describe, but this is not
guaranteed by the Standard.

[*] The only negative constants I can think of are enum
values specifically declared as negative, and character or
wide-character constants involving "extra" characters not
in the basic execution set (and even then only if `char' or
`wchar_t' is signed). Constants that "look like" numbers
are non-negative.
 
K

Keith Thompson

Keith Thompson said:
An unsuffixed hexadecimal integer constant's type is the first type
from this list:

int
unsigned int
long int
unsigned long int
long long int (C99 only)
unsigned long long int (C99 only)

in which the value can be represented. If it can't be represented in
any of those types, it may have an extended integer type (if the
implementation has extended integer types; I don't know of any that
do). If there is no type that can represent the value, the standard
doesn't say what its type is; I believe this means it invokes
undefined behavior by omission (i.e., the behavior is undefined not
because the standard says so, but because it fails to define the
behavior).

I'd be happier if the standard said something explicit about integer
constants that can't be represented in any type.
[...]

I posted a question about this in comp.std.c, and Wojtek Lerch pointed
me to a constraint in C99 6.4.4p2:

The value of a constant shall be in the range of representable
values for its type.

I think this could be worded better (there's no such thing as "its
type", since 6.4.4.1 doesn't define a type for an integer constant
that can't be represented), but it's clear enough that it's intended
to be a constraint violation.
 
D

Dave Thompson

hi all,
Out of sheer curosity, I decided to initialize an integer with a number
bigger than INT_MAX, however I still am not able to justify its output.
What is happening in here? <snip>
I guess its some kind of truncation going on .. but then why is it
ignoring MSBs ? I am also guessing this behaviour is compiler dependent
- am i correct?

Your guesses are right. Converting to a signed integer type a value
(of a wider integer type) that doesn't fit produces an
implementation-defined result, or in C99 possibly raises an
implementation-defined signal. It is very common, though not required,
to just take the lower bits, because that efficiently gives the
correct (required) result for values that _do_ fit, and the same logic
works for unsigned types which are required to take the low bits of an
unsigned or 2s-complement representation. (Officially unsigned takes
the 'modulo' value, but for 2sC that equals the low bits. The very few
if any S&M or 1sC machines must do something more complicated.)

Implementation-defined does mean that the documentation associated
with the implementation must specify what it does.

- David.Thompson1 at worldnet.att.net
 

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,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top