LTClipp
LTClipp

Reputation: 534

When is the integer width restricted?

I was having trouble writing a program that asked the user for a value N and then outputted the result 5^N. The problem was that if the user inputted a number greater than (2^31)-1, their number would overflow and the program would give them an erroneous answer.

What I did was assign the integer value given by the user to an unsigned long integer value. This way if the program could check if a number greater than (2^31)-1 was inputted because the unsigned long can hold a much higher number of positive integers than signed int can. Doing this causes the program to function as it should because I can check whether or not overflow has occurred.

However my question is this: when the user inputs a value greater than 2^31 - 1 into the original signed integer variable (which should cause it to overflow), why is it that I can then assign this overflowed value into an unsigned and get what the "correct" number is? Does overflow only happen when attempting to do operations on that number? Does the memory store the actual number (unrestricted by bit width)?

 int endCount;
unsigned long endCountUn;  /* power N */

/* Read value of N */
printf("This program will compute 5^N; enter N: ");
scanf("%d", &endCount);

/*
User's value put into unsigned long. Helps with detecting overflow.
*/
endCountUn = endCount;

if ( (endCount < 0) && (endCountUn < 2147483648) )
{
    printf("The operation is undefined for negative integers\n");
}

else if ( endCountUn > 2147483647 )
{
    printf("The value exceeds the supported numerical range\n");
}

Upvotes: 0

Views: 99

Answers (1)

BitTickler
BitTickler

Reputation: 11907

if ( (endCount < 0) && (endCountUn < 2147483648) )

The block of this if is executed for numbers n which satisfy both conditions. endCount, being a (32bit) signed integer, represented in 2's complement. The first term of the expression thus selects all n where the upper bit is set:
Range1: [0x80000000...0xFFFFFFFF]
The second term selects all n which are in the range
Range2: [0x00000000..0x7FFFFFFF].
The set of n which are in both ranges is the empty set. So, the body of your if above will never be executed.

The second if (else if part) asks for values in range 1.

So, your test code could be simplified to:

if( endCount < 0 ) { printf("Value out of range"); }

Because, no matter what the user enters (a negative or a value in Range 1), endCount will always be negative.

Finally, if you only want to allow unsigned integer values, why do you use scanf("%d",endCount) in the first place?
You could write instead:

uint32_t endCount = 0; // unsigned int is machine dependent...better use stdint.h...
...
scanf("%u", &endCount);

Output for a statement which would be intended to yield the second printf...

This program will compute 5^N; enter N: 2147483648
The value exceeds the supported numerical range

Output for a statement which would be intended to yield the first printf...

This program will compute 5^N; enter N: -10
The value exceeds the supported numerical range

Please look what this program outputs on your system for this...

uint32_t endCount;

/* Read value of N */
printf("This program will compute 5^N; enter N: ");
scanf("%u", &endCount);

printf("entered value = %d (as signed)\n",endCount);
printf("entered value = %u (as unsigned)\n",endCount);

On my system:

This program will compute 5^N; enter N: -10
entered value = -10 (as signed)
entered value = 4294967286 (as unsigned)

Upvotes: 1

Related Questions