我将如何在 C 中编写自己的新格式说明符?

How would I write my own new format specifier in C?

是否可以用 C 编写新的格式说明符?例如,假设 %g 是一个格式说明符,它以 A.B.C.D 格式从等效的无符号整数打印 ip 地址。

int ip_addr = Some integer

printf("ip address = %g", ip_addr);

输出:以A.B.C.D格式打印IP地址

虽然您可以编写一个包装函数,它将接受 %g 并依次调用 printf.

,但您不能更改标准库函数

您将不得不重新实现 printf 函数(更准确地说是它的格式解析函数)。你可以做的是将 printf 包装在一个支持 ip 地址的函数中,或者这样做:

#define FMT_IP "%d.%d.%d.%d"
#define FMT_IP_ARG(ip) getA(ip), getB(ip), getC(ip), getD(ip)

其中 getX 函数或宏获取表示 IP 地址的给定整数的 X 部分。

然后:

printf("ip address = " FMT_IP "\n", FMT_IP_ARG(ip));

添加新说明符涉及 re-writing printf() 或制作您自己的函数来处理新说明符以及 printf() 并调用它。这两种方法都很难。


另一种方法是使用 "%s" 并编写您自己的函数来形成字符串。

对于 C99 或更高版本,使用复合文字来形成所需的缓冲区 space。

#include <stdio.h>
#define MYIP_N 16
#define MYIP(ip) myip((char [MYIP_N]){""}, (ip))

char *myip(char *dest, int ip) {
  snprintf(dest, MYIP_N, "%d.%d.%d.%d", (ip >> 24) & 255, (ip >> 16) & 255,
      (ip >> 8) & 255, (ip >> 0) & 255);
  return dest;
}


int main(void) {
  int ip1 = 0x01020304;
  int ip2 = 0x05060708;
  printf("%s %s\n", MYIP(ip1), MYIP(ip2));
  return 0;
}

输出

1.2.3.4 5.6.7.8

这适用于 printf()fprintf()sprintf(),甚至 puts()

puts(MYIP(ip1));

1.2.3.4

我会选择 ,它简单且便携,前提是您知道需要多大的临时缓冲区。

但是,如果您使用的是 GNU 库 (glibc),则可以使用新的说明符扩展 printf。强烈建议您使用 upper-case 字母作为格式代码,因为几乎所有 lower-case 格式代码都在使用,其余的可能会被未来的 C/Posix 标准使用。该工具记录在 glibc manual.

基于 GNU 工具,为 BSD 库编写了一个类似的 pretty-much-compatible 工具。显然,它在 Mac OS X 上可用,尽管我不能保证这一事实。我确实在 xprintf(3) and xprintf(5).

的 Apple on-line 手册页中找到了它

上面链接的文档中有示例。