【问题标题】:What is the purpose of format specifier "%qd" in `printf()`?`printf()` 中格式说明符“%qd”的用途是什么?
【发布时间】:2018-11-22 15:03:19
【问题描述】:

我在浏览github 代码时看到了格式说明符%qd。然后我检查了 GCC 编译器,它工作正常。

#include <stdio.h>

int main()
{  
    long long num = 1;
    printf("%qd\n", num);
    return 0;
}

printf() 中格式说明符 %qd 的用途是什么?

【问题讨论】:

  • 更便携的例子可能是int64_t。但也不错的问答
  • q 长度修饰符是一种不可移植的、不可靠的、过时的、已弃用的 ll 的书写方式。在您的代码中使用ll;鼓励那些在 GitHub 上维护代码的人升级到标准 C99 格式。
  • printf 格式由运行时库实现,而不是由编译器实现。这不是 gcc(或 egcs 或 llvm)问题。例如,在我的 Ubuntu 20.04 系统上,%qd 与 gcc 和 glibc 一起工作,但在 gcc 和 musl 上失败——相同的编译器,不同的运行时库。

标签: c gcc format-specifiers openbsd


【解决方案1】:

%qd 旨在舒适地处理所有 64 位 机器,最初是一个 bsd-ism (quad_t)。

但是,egcs(以及之前的gcc)将其视为等同于ll,即 并不总是等价的:openbsd-alpha 配置为使long 是 64 位,因此quad_t 的类型定义为long。 在那种特殊情况下,类似 printf 的属性不能作为 有意的。

如果sizeof(long long) == sizeof(long) 在 openbsd-alpha 上,它应该可以工作 无论如何 - 即 %ld%lld%qd 应该可以互换。在 OpenBSD/alpha 上,sizeof(long) == sizeof(long long) == 8

在广泛使用 ISO C99 扩展之前,已经存在几个特定于平台的长度选项,q 就是其中之一。它用于整数类型,这导致printf 需要一个 64 位(四字)整数参数。常见于 BSD 平台。

但是,C99 和 C11 都没有提到长度修饰符 qfprintf() 的 macOS (BSD) 手册页将 q 标记为已弃用。因此,建议使用ll 而不是q

参考资料:

https://gcc.gnu.org/ml/gcc-bugs/1999-02n/msg00166.html

https://en.wikipedia.org/wiki/Printf_format_string

https://port70.net/~nsz/c/c11/n1570.html#7.21.6.1p7

【讨论】:

  • printf 格式由运行时库实现,而不是由编译器实现。这不是 gcc(或 egcs 或 llvm)问题。例如,在我的 Ubuntu 20.04 系统上,%qd 与 gcc 和 glibc 一起工作,但在 gcc 和 musl 上失败——相同的编译器,不同的运行时库。
【解决方案2】:

q 表示 printf 函数中的 quad word 格式说明符,用于在所有机器上轻松处理 64 位

来自Wikipedia

此外,在广泛使用 ISO C99 扩展之前,已经存在几个特定于平台的长度选项:

q - 对于整数类型,导致 printf 期望 64 位(四字) 整数参数。常见于 BSD 平台

【讨论】:

  • 顺便提一下,供以后参考。 ask a question 表单底部有一个“回答您自己的问题”复选框。它允许您将它们一起发布,而不是匆忙分开一分钟。
  • C99 没有提到长度修饰符 q,C11 也没有(参见 §7.21.6.1 The fprintf function ¶7)。 fprintf() 的 macOS (BSD) 手册页将 q 标记为已弃用。 Wikipedia 页面并未将其描述为 C99 扩展,而是将其描述为在创建 C99 扩展之前存在的特定于平台的选项。
  • 重要的是要强调这是一个 GNU C 扩展,它从来不是 C 语言的一部分。我在问题中添加了 gcc 标签。
【解决方案3】:

要回答的最有趣的 C 语言相关问题之一。符号文字“%qd” 表示为四字,在C 编程语言中通过printf 函数指定用于有效处理64 位。还请记住,从 1999 年版的 C 标准中声明 sizeof(long long) &gt;= sizeof(long),可以推断出 long long 的范围至少有 64 位。

【讨论】:

  • 由于long的最小尺寸是32位,sizeof(long long) &gt;= sizeof(long)这个事实只能让你推断long long的尺寸必须至少是32位。但是,C11 §5.2.4.2.1 Sizes of integer types &lt;limits.h&gt; 说:……它们的实现定义的值的幅度(绝对值)应等于或大于所示的值,具有相同的符号。 ... long long int LLONG_MIN -9223372036854775807 // −(2⁶³ − 1) 类型的对象的最小值,这确实要求 long long 是 64 位类型。
猜你喜欢
  • 2013-06-22
  • 2013-06-22
  • 1970-01-01
  • 2017-11-16
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 2012-05-17
  • 2012-05-17
相关资源
最近更新 更多