Search code examples
ctypesunsignedunsigned-integer

Problem with printing unsigned long integers


I have the following simple program that reads in a number given as a string and prints it. It works for small numbers, but when I try to use numbers of size unsigned long, like "18446744073709551615", it does not yield the expected results. Here is my code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void readNumbers(char* numbers, unsigned long numbers_length, unsigned long* number)
{
    char string[numbers_length + 1];
    strncpy(string, numbers + 0, numbers_length);
    *number = strtoul(string, NULL, 10);
}

int main () {

  unsigned long number;

  char* numbers = "18446744073709551615";
  unsigned long numbers_length = strlen(numbers);
  readNumbers(numbers, numbers_length, &number);
  printf("X = %lu \n", number);            // prints 4294967295

  return 0;
}

Edit_1: According to this site the maximum value of unsigned long is 18446744073709551615.

Edit_2: The following code works on my system:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

void readNumbers(char* numbers, int numbers_length, unsigned long long* number)
{
    char string[numbers_length + 1];
    strncpy(string, numbers + 0, numbers_length);
    string[numbers_length] = '\0';
    *number = strtoull(string, NULL, 10);
}


int main () {

  unsigned long long number;

  char* numbers = "18446744073709551615";
  int numbers_length = strlen(numbers);
  readNumbers(numbers, numbers_length, &number);
  printf("X = %llu \n", number);       
  return 0;
}

Solution

  • The ISO C standard only requires that the data type unsigned long is able to represent numbers in the range from 0 to 4,294,967,295.

    On some platforms, it is common for unsigned long to be able to represent larger numbers than required by the ISO C standard. For example, on 64-bit Linux, it is common for unsigned long to be able to represent numbers up to 18,446,744,073,709,551,615. But on other platforms, such as 64-bit Microsoft Windows, it is common for unsigned long to only be able to represent numbers up to 4,294,967,295, i.e. the minimum amount required by the ISO C standard.

    In contrast to unsigned long, the data type unsigned long long is guaranteed by the ISO C standard to be able to represent values up to at least 18,446,744,073,709,551,615 on all platforms.

    In order to determine the maximum number that is representable in an unsigned long on your platform, you can check the value of the macro constant ULONG_MAX.

    Similarly, in order to determine the maximum number that is representable in an unsigned long long on your platform, you can check the value of the macro constant ULLONG_MAX.

    Here is an example program:

    #include <stdio.h>
    #include <limits.h>
    
    int main( void )
    {
        printf( "  UINT_MAX: %u\n",   UINT_MAX );
        printf( " ULONG_MAX: %lu\n",  ULONG_MAX );
        printf( "ULLONG_MAX: %llu\n", ULLONG_MAX );
    }
    

    On 64-bit Microsoft Windows using MS Visual Studio, I get the following output:

      UINT_MAX: 4294967295
     ULONG_MAX: 4294967295
    ULLONG_MAX: 18446744073709551615
    

    On 64-bit Linux, I get the following output:

      UINT_MAX: 4294967295
     ULONG_MAX: 18446744073709551615
    ULLONG_MAX: 18446744073709551615
    

    UINT_MAX is the maximum value representable in an unsigned int.