如何在C中打印int64_t类型


298

C99标准具有整数类型,其字节大小如int64_t。我正在使用以下代码:

#include <stdio.h>
#include <stdint.h>
int64_t my_int = 999999999999999999;
printf("This is my_int: %I64d\n", my_int);

我收到此编译器警告:

warning: format ‘%I64d expects type int’, but argument 2 has type int64_t

我尝试了:

printf("This is my_int: %lld\n", my_int); // long long decimal

但是我得到同样的警告。我正在使用此编译器:

~/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)

在没有警告的情况下应该使用哪种格式来打印my_int变量?


Answers:


419

对于int64_t类型:

#include <inttypes.h>
int64_t t;
printf("%" PRId64 "\n", t);

对于uint64_t类型:

#include <inttypes.h>
uint64_t t;
printf("%" PRIu64 "\n", t);

您也可以使用PRIx64十六进制打印。

cppreference.com完整列出了包括intptr_tPRIxPTR)在内的所有类型的可用宏。scanf有单独的宏,例如SCNd64


PRIu16的典型定义是"hu",因此隐式字符串常量连接在编译时发生。

为了使代码完全可移植,必须使用PRId32等等进行打印int32_t"%d"或类似方法进行打印int


18
格式化宏常量的完整列表:en.cppreference.com/w/cpp/types/integer
Massood Khaari 2013年

12
并且,如果在Linux上使用C ++,请确保在加入#define __STDC_FORMAT_MACROS之前先进行操作inttypes.h
csl

17
PRId64是内部转换为的宏"lld"。因此,它与写作一样好。printf("%lld\n", t);请参阅说明:qnx.com/developers/docs/6.5.0/…–
Gaurav,

24
@Gaurav,在某些平台上是正确的,但在所有平台上并非如此。例如,在我的amd64 Linux计算机上,PRId64定义为ld。可移植性是宏的原因。
Ethan T

10
我觉得跟他们可以使人们更加厌恶一些额外的努力
帕维尔·P

64

C99的方式是

#include <inttypes.h>
int64_t my_int = 999999999999999999;
printf("%" PRId64 "\n", my_int);

否则你可以投!

printf("%ld", (long)my_int);
printf("%lld", (long long)my_int); /* C89 didn't define `long long` */
printf("%f", (double)my_int);

如果您坚持使用C89实现(尤其是Visual Studio),则可以使用开放源代码<inttypes.h>(和<stdint.h>):http : //code.google.com/p/msinttypes/


当使用来自code.google.com链接的msinttypes时,我需要定义__STDC_FORMAT_MACROS。请参阅stackoverflow.com/questions/8132399/how-to-printf-uint64-t
2014年

感谢您的注意,@ ariscris。看来,宏仅是C ++所必需的。链接到的代码中的定义位于#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
pmg

19

使用C99时,%j长度修饰符还可与printf系列函数一起使用,以打印type int64_t和的值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;
}

使用以下代码编译该代码gcc -Wall -pedantic -std=c99不会产生警告,并且程序将输出预期的输出:

a=-9223372036854775808 (0x8000000000000000)
b=9223372036854775808 (0x8000000000000000)

这是根据printf(3)我的Linux系统上的(手册页专门说的,j它用于指示在stdint.h中对intmax_tor或uintmax_t; 的转换,两者int64_tintmax_ttype的定义方式完全相同,对于相似uint64_t)。我不确定这是否可以完美移植到其他系统。


12
如果%jdprnts是intmax_t正确的调用printf("a=%jd (0x%jx)", (intmax_t) a, (intmax_t) a)。无法保证int64_tintmax_t是相同的类型,如果不相同,则行为是不确定的。
user4815162342

4
您可以移植应用%jd到打印int64_t的值,如果你明确地将它们转换为intmax_t它们传递给前printfprintf("a=%jd\n", (intmax_t)a)。这样可以避免<inttypes.h>宏的(IMHO)丑陋。当然,这假设您的实现支持%jdint64_t以及intmax_t所有这些都是由C99加入。
基思·汤普森

2
@KeithThompson'Ugliness'太过友好了。太可怕了 真可怕 令人恶心。这真是令人尴尬。或者至少应该让他们感到尴尬,这是很多介绍的原因。我从未见过这些宏,但会做这个答案和评论-包括您的-建议。
Pryftan

@Pryftan我不找到他们非常丑如你做-我不能肯定他们如何能在一个不太难看的方式没有改变的语言来定义。
Keith Thompson

@KeithThompson好吧,我很感激您至少强调了“相当”一词。好吧,其实没关系。我不明白为什么宏必须在那里。正如您所说的,您可以随便携带……等等,但是后来我也发现,关键字数量的增加也势不可挡。
Pryftan

12

来自嵌入式世界,即使uclibc也不总是可用,并且类似

uint64_t myval = 0xdeadfacedeadbeef; printf("%llx", myval);

正在打印您的废话或根本不工作-我始终使用一个小帮手,这使我可以正确转储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;
}

如果嵌入式应用程序遇到此问题,那么这就是您想要的。这个解决方案对我有用。谢谢@ataraxic。
Logan859

8

在Windows环境中使用

%I64d

在Linux中使用

%lld

18
%lld对于格式long long int,这是必然相同int64_t<stdint.h>有一个宏,用于的正确格式int64_t;参见ouah的回答
基思·汤普森

@KeithThompson但是,由于long long至少是64位,printf("%lld", (long long)x);应该可以工作,除了-0x8000000000000000之外,它不能表示为long long如果该类型未使用二进制补码。
Pascal Cuoq 2013年

@PascalCuoq:是的,它应该与强制类型转换一起使用(并且您提到的异常可能性很小,仅适用于支持二进制补码但不用于的系统long long)。
基思·汤普森

-3

//VC6.0(386及更高版本)

    __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);

问候。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.