【问题标题】:How to print a int64_t type in C如何在 C 中打印 int64_t 类型
【发布时间】:2023-03-26 06:45:01
【问题描述】:

C99 标准具有字节大小的整数类型,如 int64_t。我目前使用的是 Windows 的%I64d 格式(或未签名的%I64u),例如:

#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 变量而不出现警告?

【问题讨论】:

标签: c stdint


【解决方案1】:

对于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 has a full listing 适用于所有类型的可用宏,包括intptr_t (PRIxPTR)。 scanf 有单独的宏,例如SCNd64。


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

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

【讨论】:

  • 格式化宏常量的完整列表:en.cppreference.com/w/cpp/types/integer
  • 而且,如果在 Linux 上使用 C++,请确保在包含 inttypes.h 之前先#define __STDC_FORMAT_MACROS。
  • PRId64 是一个内部转换为"lld" 的宏。所以,不如写printf("%lld\n", t); 见描述:qnx.com/developers/docs/6.5.0/…
  • @Gaurav,在某些平台上确实如此,但并非全部。例如,在我的 amd64 Linux 机器上,PRId64 定义为ld。可移植性是宏的原因。
  • 我认为如果再付出一些额外的努力,他们本可以让它变得更加令人讨厌
【解决方案2】:

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),您或许可以使用开源 &lt;inttypes.h&gt;(和 &lt;stdint.h&gt;):http://code.google.com/p/msinttypes/

【讨论】:

  • 当使用来自 code.google.com 链接的 msinttypes 时,我需要定义 __STDC_FORMAT_MACROS。见stackoverflow.com/questions/8132399/how-to-printf-uint64-t。
  • 感谢@ariscris 的提醒。不过,似乎只有 C++ 才需要宏。链接到的代码中的定义位于#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
【解决方案3】:

在 C99 中,%j 长度修饰符还可以与 printf 系列函数一起使用,以打印 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)

这是根据我的 Linux 系统上的printf(3)(手册页特别指出j 用于指示转换为intmax_t 或uintmax_t;在我的stdint.h 中,int64_t和intmax_t 以完全相同的方式进行类型定义,uint64_t 也是如此。我不确定这是否可以完美地移植到其他系统。

【讨论】:

  • 如果%jd prnts 一个intmax_t,正确的调用将是printf("a=%jd (0x%jx)", (intmax_t) a, (intmax_t) a)。不能保证int64_t 和intmax_t 是同一类型,如果不是,则行为未定义。
  • 您可以便携地使用%jd 打印int64_t 值如果您在将它们传递给printf 之前将它们显式转换为intmax_t:printf("a=%jd\n", (intmax_t)a)。这避免了 &lt;inttypes.h&gt; 宏的(恕我直言)丑陋。当然这假设你的实现支持%jd、int64_t和intmax_t,所有这些都是由C99添加的。
  • @KeithThompson 'Ugliness' 说得太远太友好了。这绝对是可怕的。太可怕了令人作呕。令人尴尬的是它是什么。或者至少他们应该感到尴尬,介绍了这一点。我从未见过这些宏,但按照这个答案和 cmets(包括你的)的建议去做。
  • @Pryftan 我没有相当觉得它们像你一样丑陋——而且我完全不确定如何以不那么丑陋的方式定义它们无需更改语言。
  • @KeithThompson 好吧,我很感激你至少强调了“相当”这个词。好吧其实没关系。我不明白为什么宏必须在那里。正如你所说,你可以随身携带......等等。但我也发现关键字数量的增加也已经失控了。
【解决方案4】:

来自嵌入式世界,即使是 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;
}

【讨论】:

  • buf 的大小不应该是 34+1 吗? char 数组不会以空值终止 atm。
【解决方案5】:

windows环境下,使用

%I64d

在 Linux 中,使用

%lld

【讨论】:

  • %lld 是long long int 的格式,它不一定与int64_t 相同。 &lt;stdint.h&gt; 有一个用于int64_t 正确格式的宏;见ouah's answer。
  • @KeithThompson 但是,由于 long long 至少是 64 位,printf("%lld", (long long)x); 应该可以工作,除了 -0x80000000000000000,如果该类型是不使用二进制补码。
  • @PascalCuoq:是的,它应该适用于演员表(你提到的例外情况不太可能,仅适用于支持二进制补码但不将其用于long long 的系统) .
【解决方案6】:

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

问候。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    • 2019-07-21
    • 2016-01-10
    • 2021-11-26
    • 1970-01-01
    相关资源
    最近更新 更多