Search code examples
cstrtol

strtoul giving unexpected output


I am trying to use the strtoul function, but as shown below it is returning an unexpected value (adding ff's in the beginning):

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

main() {
    unsigned long temp ;
    char *err;
    temp = strtoul("3334444444",&err,10);
    if (temp > UINT_MAX) {
        printf("%lx %x %x\n",temp,3334444444,UINT_MAX);
    }else 
        printf("%lx %x\n",temp,3334444444);
}

$./a.out
ffffffffc6bf959c c6bf959c ffffffff 

The above output corresponds to the if part being true, though I expect the else part to get executed here. Can anyone please explain why strtoul is behaving like this? Why does it return ffffffffc6bf959c rather than just c6bf959c? If I use "333444444" (i.e. just one 4 less) rather than "3334444444" in the above code, then I get the correct output (i.e. 13dff55c 13dff55c) corresponding to the else part.

Note : As pointed by melpomene in his reply below, stdlib.h header file should have been included and that will resolve the issue. Can anyone please let me know what is being done by the program by assuming the incorrect return type (int in this case) during compile time which can't be undone (or atleast it is not getting undone in this case) even after knowing the correct return type (unsigned long in this case) during link time ? In short, i want to know how c6bf959c is getting converted to ffffffffc6bf959c because of prototype not provided.


Solution

  • Compiling your code with gcc with warnings enabled gives:

    try.c:5:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
     main() {
     ^~~~
    try.c:5:1: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
    try.c: In function ‘main’:
    try.c:8:12: warning: implicit declaration of function ‘strtoul’ [-Wimplicit-function-declaration]
         temp = strtoul("3334444444",&err,10);
                ^~~~~~~
    try.c:8:5: warning: nested extern declaration of ‘strtoul’ [-Wnested-externs]
         temp = strtoul("3334444444",&err,10);
         ^~~~
    try.c:10:22: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 3 has type ‘long long int’ [-Wformat=]
             printf("%lx %x %x\n",temp,3334444444,UINT_MAX);
                          ^
    try.c:12:22: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 3 has type ‘long long int’ [-Wformat=]
             printf("%lx %x\n",temp,3334444444);
                          ^
    

    The main problem is implicit declaration of function ‘strtoul’, indicating that the function is not declared (and thus assumed to return int) because you forgot to #include <stdlib.h>. Adding the missing #include fixes the value of temp.

    But you should also have a look at the warnings reported for printf and fix those.