Why is strtol() returning 0x7fffffff instead of the expected 0xAABBCCDD?

168 views Asked by At
// msvc 17.3.5
// sizeof (long) : 4
#include <stdlib.h>
int main(){
    long i = 0xAABBCCDD;// 0x AABBCCDD in debugger window

    char number[] = "AABBCCDD EEFF";
    char* p;
    long var = strtol ( number, &p, 16 );// 0x 7FFF FFFF
    perror ( "?:" ); // ?:: Result too large
}

I tried char number[] = "AABBCC EEFF"; and it works fine. I expect 0xAABBCCDD inside var instead 0x7fffffff. What is wrong?

1

There are 1 answers

6
Vlad from Moscow On BEST ANSWER

From the C Standard (7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions)

8 The strtol, strtoll, strtoul, and strtoull functions return the converted value, if any. If no conversion could be performed, zero is returned. If the correct value is outside the range of representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, or ULLONG_MAX is returned (according to the return type and sign of the value, if any), and the value of the macro ERANGE is stored in errno.

The positive hexadecimal constant 0xAABBCCDD can not be represented in an object of the signed type long int provided that sizeof( long int ) is equal to 4.

For example try this demonstration program

#include <stddef.h>
#include <stdio.h>

int main( void )
{
    printf( "%#X\n", LONG_MAX );
}

The program output is

0X7FFFFFFF

Note: as in this case sizeof( long ) is equal to sizeof( unsigned int ) and the value is representable in an object of the type unsigned int there is used the conversion specifier X. Otherwise you need to include header <inttypes.h> and to use a macro as for example PRIX32.

As you can see LONG_MAX (the maximum positive value that can be stored in an object of the type long int) is less than the positive hexadecimal constant 0xAABBCCDD.

Instead of using the function strtol use function strtoul

unsigned long var = strtoul ( number, &p, 16 );

Or if you want to deal with signed integers then use function strtoll.