2

Can anyone explain the output of this program and how I can fix it?

unsigned long long ns = strtoull("123110724001300", (char **)NULL, 10);
fprintf(stderr, "%llu\n", ns);

// 18446744073490980372
user105033
  • 18,800
  • 19
  • 58
  • 69

3 Answers3

11

Do you have <stdlib.h> included?

I can reproduce on MacOS X if I omit <stdlib.h>.

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

int main(void)
{
    unsigned long long ns = strtoll("123110724001300", (char **)NULL, 10);
    printf("%llu\n", ns);
    return(0);
}

Omit the header, I get your result. Include the header, I get the correct answer.

Both 32-bit and 64-bit compiles.


As noted in the comments, in the absence of a declaration for strtoll(), the compiler treats it as a function returning int.

To see more of what goes on, look at the hex outputs:

     123110724001300    0x00006FF7_F2F8DE14    Correct
18446744073490980372    0xFFFFFFFF_F2F8DE14    Incorrect

Manually inserted underscores...

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    Ahh, that makes sense. In the absence of a declaration for `strtoll`, it's treated as `int strtoll()`, so what ends up at `ns` is essentially undefined. – Pavel Minaev Oct 29 '09 at 19:52
  • 1
    I was curious why that is so, so I did some digging. Turns out, (int)strtoll(...) produces the same result as missing stdlib.h . C assumes that the return value of a function is int by default, so only part of strtoll's result is taken. –  Oct 29 '09 at 19:55
  • 4
    If this happens and you've not noticed it, your warning levels aren't high enough. – Tim Oct 29 '09 at 19:58
  • 1
    That's default warning level for gcc. More reasons to compile C code with C++ compiler... –  Oct 29 '09 at 20:07
  • 4
    @Tim: actually, you don't even need to increase the warning levels: it's enough to switch from the 20-year-old language version to the ten-year-old one (ie `-std=c99` or `-std=gnu99`); throwing in some additional flags like `-pedantic -Wall -Wextra` shouldn't hurt, though – Christoph Oct 29 '09 at 20:30
  • I usually use '-Wall -Wextra -std=c99 -pedantic -Wmissing-prototypes -Wstrict-prototypes', and sometimes '-Werror' (when I'm confident the code is portable and reliable enough). – Jonathan Leffler Oct 29 '09 at 21:59
  • see http://stackoverflow.com/questions/432835/how-do-you-ensure-that-you-as-programmer-have-written-quality-c-code/432852#432852 and http://stackoverflow.com/questions/154630/recommended-gcc-warning-options-for-c/415171#415171 for more options beyond `-Wall -Wextra` – Christoph Oct 29 '09 at 22:54
  • See also: http://stackoverflow.com/questions/393208/what-is-the-best-command-line-tool-to-clean-up-code/ – Jonathan Leffler Oct 30 '09 at 01:56
3

Why not use strtoull if you want an unsigned long long?

Tola Odejayi
  • 3,019
  • 9
  • 31
  • 46
1

I cannot explain the behavior. However, on 32 bit Windows XP with Cygwin gcc-4.3.2:

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

int main(void) {
    unsigned long long ns = strtoull("123110724001300", NULL, 10);
    fprintf(stderr, "%llu\n", ns);
    return 0;
}

prints

E:\Home> t.exe
123110724001300
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339