Shota
Shota

Reputation: 7330

Comparing INT_MAX and long giving wrong result

I am getting long from user input (with fgets() and converting to long with strtoul()), but when testing it to convert into integer giving wrong result.

Declarations:

char buf[BUFSIZE];
unsigned char input[80];
int done = 0;
int i, val;
long valPrimary;
char *ptr;

Code:

 // gets the max first 79 characters, whichever comes first
 if (fgets(input, INPUTSIZE, stdin) != NULL) {
        printf("Input ok\n");
 } else {
    printf("Input not ok\n");
    return 0;
 }

// get unsigned long from input
valPrimary = strtoul(input, &ptr, 10);      

// Check if any character was converted 
if (ptr == input) {
    fprintf(stderr, "Can't convert string to number\n");
    return 0;
}       

if ((valPrimary == LONG_MAX || valPrimary == LONG_MIN) && errno== ERANGE) {
    fprintf(stderr, "Number out of range for LONG\n");      
    return 0;
}    
printf("valPrimary: %lu\n", valPrimary);
printf("Max Int: %i\n", INT_MAX);
printf("Min Int: %i\n", INT_MIN);
printf("Long size: %lu\n", sizeof(long));

// Check overflows and if long is convertable to int
if ( (valPrimary > INT_MAX) || (valPrimary < INT_MIN) ) {
    fprintf(stderr, "Number out of range for INT\n");
    return 0;
} else {
    val = (int) valPrimary;
}

For example if I enter some a very big number, I am getting this kind of stdout:

valPrimary: 18446744073709551615

Max Int: 2147483647

But error message is not displayed and conversion still happens.

Upvotes: 1

Views: 1037

Answers (2)

Alderath
Alderath

Reputation: 3859

Probably, what is happening is this:

valPrimary is declared as: long valPrimary; rather than: unsigned long valPrimary

The decimal value 18446744073709551615 corresponds to hexadecimal value 0xffffffffffffffff.

When this value is stored in a signed long, the first bit is the sign bit. In fact, 0xffffffffffffffff in a signed long is equal to -1.

Hece, the conversion is made, and -1 is returned, since INT_MAX > -1 > INT_MIN

Upvotes: 1

chux
chux

Reputation: 153447

Incorrect mixing of signed long and strtoul(). Use strtol(). @Quentin
strtoul("18446744073709551615",...) --> ULONG_MAX and that converted to long likely becomes -1.

long valPrimary;
...
// valPrimary = strtoul(input, &ptr, 10);      
valPrimary = strtol(input, &ptr, 10);      
...
if ((valPrimary == LONG_MAX || valPrimary == LONG_MIN) && errno== ERANGE) {
  fprintf(stderr, "Number out of range for LONG\n");      

Upvotes: 1

Related Questions