How do you format an unsigned long long int using printf?
Asked Answered
P

14

467
#include <stdio.h>
int main() {
    unsigned long long int num = 285212672; //FYI: fits in 29 bits
    int normalInt = 5;
    printf("My number is %d bytes wide and its value is %ul. A normal number is %d.\n", sizeof(num), num, normalInt);
    return 0;
}

Output:

My number is 8 bytes wide and its value is 285212672l. A normal number is 0.

I assume this unexpected result is from printing the unsigned long long int. How do you printf() an unsigned long long int?

Poulin answered 5/8, 2008 at 20:59 Comment(4)
I just compiled your code ( with %llu ) with gcc and the output was the correct one. Are you passing any options to the compiler?Molini
Note that samsung bada's newlib seems not to support "%lld" : developer.bada.com/forum/…Visit
See also https://mcmap.net/q/81285/-sprintf-for-unsigned-_int64Stellular
I would suggest using using stdint.h and being explicit about the number of bits in your variable. We're still in a period of transition between 32 and 64 bit architectures, and "unsigned long long int" doesn't mean the same thing on both.Millur
M
606

Use the ll (el-el) long-long modifier with the u (unsigned) conversion. (Works in windows, GNU).

printf("%llu", 285212672);
Michaelis answered 5/8, 2008 at 21:2 Comment(10)
Or to be precise it's for GNU libc, and doesn't work with Microsoft's C runtime.Obbligato
This isn't a Linux/UNIX thing, the "ll" length modifier was added to Standard C in C99, if it doesn't work in "Microsoft C" then it is because they are not standards compliant.Piroshki
Works in Turbo C++ on WindowsSurvivor
Works for me in VS2008. Moreover, as far as I remember the MS C Compiler (when set up to compile straight C) is supposed to be C90 compliant by design; C99 introduced some things that not everyone liked.Liesa
One thing to keep in mind here is that if you are passing multiple long long arguments to printf and use the wrong format for one of them, say %d instead of %lld, then even the arguments printed after the incorrect one may be completely off (or can even cause printf to crash). Essentially, variable arguments are passed to printf without any type information, so if the format string is incorrect, the result is unpredictable.Washable
Heard Herb Sutter say in an interview that Microsoft's customers don't ask for C99 so their pure C compiler has been frozen at C90. That applies if you are compiling as C. If you compile as C++, as others have noted above, you should be fine.Immediate
everything changes with 64 bit machineKoblick
Using the Cygwin compiler that cross-compiles to x86_64 (x86_64-w64-mingw32-g++) %lx with a long long unsigned int gives an error that the format and type don't go together, and using %llx with the same variable and same compiler gives an error that %llx is an unknown format. And the variable is actually a pthread_t. So it doesn't "work in Windows/GNU" and the problem is not that it's Microsoft's compiler.Messy
For Hex output, an unsigned long long would be printed with %I64x. The virtually portable way is to cast the number to intmax_t and use PRIXMAX. And to use PRIXMAX or anything like it with C++ in a GNU compiler, you have to #define __STDC_FORMAT_MACROS. And in the conditions I'm describing, the definition of PRIXMAX I get appears to be the wrong one and I have to force %I64X which works.Messy
Why not ull instead of llu?Aircrewman
S
160

%d--> for int

%u--> for unsigned int

%ld--> for long int or long

%lu--> for unsigned long int or long unsigned int or unsigned long

%lld--> for long long int or long long

%llu--> for unsigned long long int or unsigned long long

Snowman answered 13/5, 2015 at 17:48 Comment(0)
F
114

You may want to try using the inttypes.h library that gives you types such as int32_t, int64_t, uint64_t etc. You can then use its macros such as:

#include <inttypes.h>

uint64_t x;
uint32_t y;

printf("x: %"PRIu64", y: %"PRIu32"\n", x, y);

This is "guaranteed" to not give you the same trouble as long, unsigned long long etc, since you don't have to guess how many bits are in each data type.

Filthy answered 12/8, 2008 at 11:7 Comment(10)
where these PRId64, PRId32 macros defined?Haldes
@happy_marmoset: they are defined in inttypes.hFilthy
I think you need PRIu64 and PRIu32 for unsigned integers.Helvetia
Is inttypes.h standard? Wouldn't it be stdint.h?Thistly
The ints are in both, inttypes also contain bools which can be found in stdbool.hAll
Note that these exact-width types are optional, as there are architectures out there that do not have integer types of those exact widths. Only the leastX and fastX types (which may actually be wider than indicated) are mandatory.Amalgamate
Error in code blocks: error: unknown type name 'uint64_t'; did you mean 'wint_t'?|Infelicitous
@john: no, uint64_t. I think that this is a somewhat non-standard extension, so different compilers or environments might have different names.Filthy
Nathan Fellman, Please fix this highly upvoted answer: "PRId64" --> "PRIu64". Likewise for 32-bit.Papyraceous
Thanks, I just ran some code printing uint64_t happily using %lu in Linux, and the same code was printing the values as 32 bit integers on Windows/MSVC. Using the PRIu64 macro fixed the problem.Heda
P
40

For long long (or __int64) using MSVS, you should use %I64d:

__int64 a;
time_t b;
...
fprintf(outFile,"%I64d,%I64d\n",a,b);    //I is capital i
Papilloma answered 6/9, 2009 at 14:26 Comment(0)
C
39

That is because %llu doesn't work properly under Windows and %d can't handle 64 bit integers. I suggest using PRIu64 instead and you'll find it's portable to Linux as well.

Try this instead:

#include <stdio.h>
#include <inttypes.h>

int main() {
    unsigned long long int num = 285212672; //FYI: fits in 29 bits
    int normalInt = 5;
    /* NOTE: PRIu64 is a preprocessor macro and thus should go outside the quoted string. */
    printf("My number is %d bytes wide and its value is %" PRIu64 ". A normal number is %d.\n", sizeof(num), num, normalInt);
    return 0;
}

Output

My number is 8 bytes wide and its value is 285212672. A normal number is 5.
Conversable answered 9/9, 2008 at 7:54 Comment(5)
+1 for the reference to PRIu64, which I had never seen, but this doesn't seem portable to 64 bit Linux (at least) because PRIu64 expands to "lu" instead of "llu".Millur
And why would that be bad? A long is a 64 bit value on 64 bit Linux, as on every other OS except for Windows.Unborn
@BDatRivenhill Linux/Unix uses LP64 in which long is 64 bitsVotive
however, to make it more portable, use int64_t instead because there may well be some implementations with long long larger than longVotive
"%" PRIu64 matches uint64_t and "%llu" matches unsigned long long. This answer has "%" PRIu64 with unsigned long long. This approach plants seeds for UB when unsigned long long is more than 64-bit. Best to avoid.Papyraceous
X
16

In Linux it is %llu and in Windows it is %I64u

Although I have found it doesn't work in Windows 2000, there seems to be a bug there!

Xe answered 11/9, 2008 at 0:57 Comment(4)
with windows, (or at least, with the microsoft C compiler for windows) there's also %I64d, %I32u, and %I32dFaviolafavonian
What does it have to do with Windows 2000? The C library is the one that handles printf.Darcidarcia
Just what I observed. I wrote an app which used this construct and it worked perfectly on WinXP but spat garbage on Win2k. Maybe it's something to do with a system call that the C library is making to the kernel, maybe it's something to do with Unicode, who knows. I remember having to work around it using _i64tot() or something like that.Xe
The Win2k/Win9x issue is likely due to unsigned long long datatype being relatively new (at the time, with the C99 standard) but C compilers (including MinGW/GCC) utilizing the old Microsoft C runtime which only supported the C89 spec. I only have access to really old and reasonably recent Windows API docs. So it's difficult to say exactly when I64u support was dropped in. But it sounds like the XP-era.Mousterian
P
8

Compile it as x64 with VS2005:

%llu works well.

Plata answered 11/10, 2012 at 6:23 Comment(0)
P
6

How do you format an unsigned long long int using printf?

Since C99 use an "ll" (ell-ell) before the conversion specifiers o,u,x,X.

In addition to base 10 options in many answers, there are base 16 and base 8 options:

Choices include

unsigned long long num = 285212672;
printf("Base 10: %llu\n", num);
num += 0xFFF; // For more interesting hex/octal output.
printf("Base 16: %llX\n", num); // Use uppercase A-F
printf("Base 16: %llx\n", num); // Use lowercase a-f
printf("Base  8: %llo\n", num);
puts("or 0x,0X prefix");
printf("Base 16: %#llX %#llX\n", num, 0ull); // When non-zero, print leading 0X
printf("Base 16: %#llx %#llx\n", num, 0ull); // When non-zero, print leading 0x
printf("Base 16: 0x%llX\n", num); // My hex fave: lower case prefix, with A-F

Output

Base 10: 285212672
Base 16: 11000FFF
Base 16: 11000fff
Base  8: 2100007777
or 0x,0X prefix
Base 16: 0X11000FFF 0
Base 16: 0x11000fff 0
Base 16: 0x11000FFF
Papyraceous answered 3/2, 2021 at 13:33 Comment(2)
+l: "%llu" surprised me. I used "%ull" and got warning said I provided int.Liborio
@Rainning "%ull" prints an unsigned and then "ll".Papyraceous
R
4

Apparently no one has come up with a multi-platform* solution for over a decade since [the] year 2008, so I shall append mine 😛. Plz upvote. (Joking. I don’t care.)

Solution: lltoa()

How to use:

#include <stdlib.h> /* lltoa() */
// ...
char dummy[255];
printf("Over 4 bytes: %s\n", lltoa(5555555555, dummy, 10));
printf("Another one: %s\n", lltoa(15555555555, dummy, 10));

OP’s example:

#include <stdio.h>
#include <stdlib.h> /* lltoa() */

int main() {
    unsigned long long int num = 285212672; // fits in 29 bits
    char dummy[255];
    int normalInt = 5;
    printf("My number is %d bytes wide and its value is %s. "
        "A normal number is %d.\n", 
        sizeof(num), lltoa(num, dummy, 10), normalInt);
    return 0;
}

Unlike the %lld print format string, this one works for me under 32-bit GCC on Windows.

*) Well, almost multi-platform. In MSVC, you apparently need _ui64toa() instead of lltoa().

Rarefy answered 22/3, 2019 at 19:8 Comment(3)
I don't have lltoa.Prestonprestress
lltoa() is not a standard C library function. It does not work under 32-bit GCC on Windows when compiled unless non-standard extensions are allowed.Papyraceous
sizeof(num) returns a size_t. "%d" is not specifed to work with that. Better with "%zu".Papyraceous
T
4

One possibility for formatting an unsigned long long is to make use of uintmax_t. This type has been available since C99 and unlike some of the other optional exact-width types found in stdint.h, uintmax_t is required by the Standard (as is its signed counterpart intmax_t).

According to the Standard, a uintmax_t type can represent any value of any unsigned integer type.

You can print a uintmax_t value using the %ju conversion specifier (and intmax_t can be printed using %jd). To print a value which is not already uintmax_t, you must first cast to uintmax_t to avoid undefined behavior:

#include <stdio.h>
#include <stdint.h>

int main(void) {
    unsigned long long num = 285212672;
    printf("%ju\n", (uintmax_t)num);

    return 0;
}
Trivial answered 13/9, 2022 at 22:20 Comment(2)
How rare it is that a new answer to such an old and basic question actually brings something new and useful to the conversation. And something even that was relevant at the time of the original post: uintmax_t and the j length specifier were both in C99 (but not in C90).Tarnation
Thanks @JohnBollinger -- I was surprised to find that other answers seemed to have missed this.Trivial
D
3

In addition to what people wrote years ago:

  • you might get this error on gcc/mingw:

main.c:30:3: warning: unknown conversion type character 'l' in format [-Wformat=]

printf("%llu\n", k);

Then your version of mingw does not default to c99. Add this compiler flag: -std=c99.

Downswing answered 17/1, 2016 at 12:27 Comment(0)
O
2

Non-standard things are always strange :)

for the long long portion under GNU it's L, ll or q

and under windows I believe it's ll only

Olnay answered 5/8, 2008 at 21:3 Comment(0)
H
0

Well, one way is to compile it as x64 with VS2008

This runs as you would expect:

int normalInt = 5; 
unsigned long long int num=285212672;
printf(
    "My number is %d bytes wide and its value is %ul. 
    A normal number is %d \n", 
    sizeof(num), 
    num, 
    normalInt);

For 32 bit code, we need to use the correct __int64 format specifier %I64u. So it becomes.

int normalInt = 5; 
unsigned __int64 num=285212672;
printf(
    "My number is %d bytes wide and its value is %I64u. 
    A normal number is %d", 
    sizeof(num),
    num, normalInt);

This code works for both 32 and 64 bit VS compiler.

Humeral answered 5/8, 2008 at 21:40 Comment(1)
Try an actual 64-bit number instead of '285212672' and I do not believe the first example runs correctly, compiled to any target.Soler
T
-1

Hex:

printf("64bit: %llp", 0xffffffffffffffff);

Output:

64bit: FFFFFFFFFFFFFFFF
Tampere answered 26/7, 2015 at 9:57 Comment(5)
Very nice! i was wondering how i could get it in hex representationHuai
But, almost all the C++ and C compilers give the warning: warning: use of 'll' length modifier with 'p' type character [-Wformat=]Aargau
this utterly broken answer has doubly-undefined behaviour and does not even begin to answer the question.Prestonprestress
@AnttiHaapala You say this answer is utterly broken with doubly-undefined behaviour, can you elaborate or shall I just delete it? Or keep it as a good bad example?Tampere
UB1: all pointers are same size, sizeof(char *) == sizeof(long long *), so size modifier on %p is pointless. UB2: 0xff.fff is type int and format %p expects a pointerRetrochoir

© 2022 - 2024 — McMap. All rights reserved.