tags:

views:

313

answers:

3

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
+3  A: 

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

Shoko
same thing happens with strtoull
+1  A: 

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
stdlib.h was the reason ...
Excellent. Glad it helped.
Sinan Ünür
+7  A: 

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
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
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.
Arkadiy
@Pavel Minaev :)
Arkadiy
If this happens and you've not noticed it, your warning levels aren't high enough.
Tim
That's default warning level for gcc. More reasons to compile C code with C++ compiler...
Arkadiy
Nice catch Jonathan.
Michael Burr
@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
ps: assuming gcc
Christoph
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
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
See also: http://stackoverflow.com/questions/393208/what-is-the-best-command-line-tool-to-clean-up-code/
Jonathan Leffler