Search code examples
chexlong-integerdata-conversionstrtol

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


// 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?


Solution

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