c - 具有 `fcn( char *, ...)` 的可变参数函数如何知道何时结束?

标签 c printf variadic-functions kernighan-and-ritchie

我一直在审阅来自多个来源的内容,包括我最喜欢的 K&R 第二版。

我一直在研究可变参数函数,我看到的几乎所有教程都在省略号之前使用和 int 来确定传递的变量参数总数。

但是书中的K&R例子没有使用int,他们使用的是char *

我搜索了 stackoverflow 并找到了如下内容:

Any variadic function must have a way for the caller to specify the number and types of arguments. The *printf functions, for example, do so via the (non-variadic) format string. link

No -- C doesn't define end as having any special meaning with varargs. When you write a function that takes a variable argument list, it's up to you to decide how to tell it how long of a list has been passed. link

K&R minprintf 旨在展示如何使用可变参数函数。

---- to show how to write a function that processes a variable-length argument list in a portable way. Since we are mainly interested in the argument processing, minprintf will process the format string and arguments but will call the real printf to do the format conversions

K&R只展示了功能,我在底部添加了main,看看能不能用。我用 gcc -Wall test.c 编译了它。它在没有警告的情况下编译,并且按预期工作。代码是:

#include <stdarg.h>
#include <stdio.h>

/* minprintf: minimal printf with variable argument list */
void minprintf(char *fmt, ...)
{
   va_list ap; /* points to each unnamed arg in turn */
   char *p, *sval;
   int ival;
   double dval;

   va_start(ap, fmt); /* make ap point to 1st unnamed arg */
   for (p = fmt; *p; p++) {
      if (*p != '%') {
         putchar(*p);
         continue;
      }
      switch (*++p) {
      case 'd':
         ival = va_arg(ap, int);
         printf("%d", ival);
         break;
      case 'f':
         dval = va_arg(ap, double);
         printf("%f", dval);
         break;
      case 's':
         for (sval = va_arg(ap, char *); *sval; sval++)
            putchar(*sval);
         break;
      default:
         putchar(*p);
         break;
      }
   }
   va_end(ap); /* clean up when done */
}
// I added this main below to test K&R minprintf function. It compiled no errors and gave right answer.

int main()
{
   int i = 25;
   int j = 21;
   char str[] = "This is a test";
   minprintf("%d, %d, %s\n", i, j, str);
}   

minprintf 如何知道何时结束?那里有 NULL 吗? K&R 不解释。从我在网上阅读的资料和上面的一些引述来看,可变参数函数不知道在哪里结束,除非你告诉它,比如在省略号前加上一个 int。

最佳答案

是的,里面有一个\0。查看循环的终止条件:

for (p = fmt; *p; p++) { // look here
    // ...
}

p不指向\0值时,*p != '\0',即(bool )*ptrue。在这种情况下,将处理 *p,无论是 % 还是其他。

p 指向\0 值时,(bool)*pfalse。循环结束,调用 va_end

因此,在扫描完字符串、处理所有 % 说明符后,它会通过检查字符串的结尾 来终止。

关于c - 具有 `fcn( char *, ...)` 的可变参数函数如何知道何时结束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54508542/

相关文章:

c - 在编译器之间匹配 va_list 类型

types - 在 Julia 中键入 kwargs

c:使用函数将新节点插入到单链表中

c - 使用信号量的 undefined reference 问题

matlab - 如何在 MATLAB 中显示结构数组的选定条目

C 文件读取产生意外错误

c - 通过指针从 C 和 C++ 中的函数返回本地数据

c - 我想 getchar 两次,但我不能

c - printf 输出太频繁

Java 将 Map 传递给可变参数对