可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
C99 standard has integer types with bytes size like int64_t. I am using the following code:
#include <stdio.h>
#include <stdint.h>
int64_t my_int = 999999999999999999;
printf(\"This is my_int: %I64d\\n\", my_int);
and I get this compiler warning:
warning: format ‘%I64d’ expects type ‘int’, but argument 2 has type ‘int64_t’
I tried with:
printf(\"This is my_int: %lld\\n\", my_int); // long long decimal
But I get the same warning. I am using this compiler:
~/dev/c$ cc -v
Using built-in specs.
Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5664~89/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5664)
Which format should I use to print my_int variable without having a warning?
回答1:
For int64_t
type:
#include <inttypes.h>
int64_t t;
printf(\"%\" PRId64 \"\\n\", t);
for uint64_t
type:
#include <inttypes.h>
uint64_t t;
printf(\"%\" PRIu64 \"\\n\", t);
you can also use PRIx64
to print in hexadecimal.
cppreference.com has a full listing of available macros for all types including intptr_t
(PRIxPTR
). There are separate macros for scanf, like SCNd64
.
A typical definition of PRIu16 would be \"hu\"
, so implicit string-constant concatenation happens at compile time.
For your code to be fully portable, you must use PRId32
and so on for printing int32_t
, and \"%d\"
or similar for printing int
.
回答2:
The C99 way is
#include <inttypes.h>
int64_t my_int = 999999999999999999;
printf(\"%\" PRId64 \"\\n\", my_int);
Or you could cast!
printf(\"%ld\", (long)my_int);
printf(\"%lld\", (long long)my_int); /* C89 didn\'t define `long long` */
printf(\"%f\", (double)my_int);
If you\'re stuck with a C89 implementation (notably Visual Studio) you can perhaps use an open source <inttypes.h>
(and <stdint.h>
): http://code.google.com/p/msinttypes/
回答3:
With C99 the %j
length modifier can also be used with the printf family of functions to print values of type int64_t
and uint64_t
:
#include <stdio.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
int64_t a = 1LL << 63;
uint64_t b = 1ULL << 63;
printf(\"a=%jd (0x%jx)\\n\", a, a);
printf(\"b=%ju (0x%jx)\\n\", b, b);
return 0;
}
Compiling this code with gcc -Wall -pedantic -std=c99
produces no warnings, and the program prints the expected output:
a=-9223372036854775808 (0x8000000000000000)
b=9223372036854775808 (0x8000000000000000)
This is according to printf(3)
on my Linux system (the man page specifically says that j
is used to indicate a conversion to an intmax_t
or uintmax_t
; in my stdint.h, both int64_t
and intmax_t
are typedef\'d in exactly the same way, and similarly for uint64_t
). I\'m not sure if this is perfectly portable to other systems.
回答4:
In windows environment, use
%I64d
in Linux, use
%lld
回答5:
Coming from the embedded world, where even uclibc is not always available, and code like
uint64_t myval = 0xdeadfacedeadbeef;
printf(\"%llx\", myval);
is printing you crap or not working at all -- i always use a tiny helper, that allows me to dump properly uint64_t hex:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
char* ullx(uint64_t val)
{
static char buf[34] = { [0 ... 33] = 0 };
char* out = &buf[33];
uint64_t hval = val;
unsigned int hbase = 16;
do {
*out = \"0123456789abcdef\"[hval % hbase];
--out;
hval /= hbase;
} while(hval);
*out-- = \'x\', *out = \'0\';
return out;
}
回答6:
//VC6.0 (386 & better)
__int64 my_qw_var = 0x1234567890abcdef;
__int32 v_dw_h;
__int32 v_dw_l;
__asm
{
mov eax,[dword ptr my_qw_var + 4] //dwh
mov [dword ptr v_dw_h],eax
mov eax,[dword ptr my_qw_var] //dwl
mov [dword ptr v_dw_l],eax
}
//Oops 0.8 format
printf(\"val = 0x%0.8x%0.8x\\n\", (__int32)v_dw_h, (__int32)v_dw_l);
Regards.