【问题标题】:C99: Why does %lli not match int64_t on 64bit machines?C99:为什么 %lli 在 64 位机器上不匹配 int64_t?
【发布时间】:2016-11-05 22:21:34
【问题描述】:

我将 32 位 ARM 代码移植到 64 位 x86 并遇到以下错误:

format '%lli' expects argument of type 'long long int',
but argument 3 has type 'int64_t'

我发现了很多关于在这种情况下使用 PRIi64 的信息,但没有找到关于“为什么我不能使用 lli?”的信息。

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

int main() {
    int64_t hugo = 993;
    long long int fred = 994;
    printf("%s -> %" PRIi64 " lli -> %lli\n", PRIi64, hugo, fred);
    return 0;
}

上面的代码编译没有错误并打印li -&gt; 993 lli -&gt; 994。那么,如果两者的大小相同,为什么我需要 li 用于 int64_t(8 字节)和 lli 用于 long long int(8 字节)?

我发现一篇帖子说它是a portability issue warning。所以关掉这个警告是省事吗? (我发现的唯一标志是-Wno-format,它禁用了很多检查......)

【问题讨论】:

  • lld 没有出现在您的代码中?请发布产生消息的确切代码。
  • int64_t 顾名思义是 8 个字节的固定大小。但是,long long int 的大小取决于实现。
  • 所以我希望在为lli 与给定参数不匹配的系统编译时收到此警告 - 例如其中lli 需要一个 128 位整数。
  • @Charly 根据 C 标准,即使底层类型相同,lld 也不匹配 int64_t,因此 gcc 警告您是正确的。
  • PRIu64 应该是PRIi64

标签: c gcc printf c99


【解决方案1】:

在编写标准时,许多实现都有两个或多个具有相同大小和表示的整数类型;最典型的是,intshortlong 具有相同的大小和表示形式。

即使在大小和表示匹配的平台上,从int* 转换为short*long* 也需要强制转换,但在对两个(或更多)类型使用相同表示的实现上,指针任何一个都可以用来访问另一个的数据。对这种用法的支持不被认为是 C 的“扩展”,而更像是“好吧,它还能做什么?”这似乎很明显,不需要文档(*)

然而,gcc 的作者假定,不会使用指向非字符整数类型的指针来访问任何其他非字符整数类型的东西——即使是那些大小和表示相同的东西时间>。由于printf 将使用long long int* 读取%lld 的参数,long* 读取%ld 的参数,并使用int* 读取%d 的参数,gcc 的作者将查看任何尝试使用%lldint64_t 类型的参数处理为未定义行为,在该类型被定义为long long 以外的其他东西的实现上,即使它的大小和表示符合预期。

(*)虽然 C89 要求记录所有“扩展”,但列出常见扩展的附件并未列出。由于标准的作者不可能没有意识到许多——如果不是大多数的话——编译器有两个或多个整数类型,它们共享相同的大小和表示,并允许指向这些类型的指针可以互换使用,唯一合理的结论可能是他们不认为这种行为是需要文档的“扩展”。

【讨论】:

    猜你喜欢
    • 2015-12-05
    • 2018-10-26
    • 1970-01-01
    • 2015-04-02
    • 2014-06-27
    • 2015-10-29
    • 2021-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多