【问题标题】:Variable Length Arguments without using stdarg.h不使用 stdarg.h 的可变长度参数
【发布时间】:2013-03-05 05:07:31
【问题描述】:

我试图通过检查堆栈来理解和实现一种处理可变长度参数函数的方法,但我不知道从哪里以及如何开始。我发现以下链接很有帮助,但我仍然不太明白如何在 c 中实现类似打印功能的功能。

http://www.swig.org/Doc1.3/Varargs.html

Trailing dots (...) within function argument list in C++

【问题讨论】:

  • 为什么要在不使用stdarg.h的情况下这样做?
  • stdarg.h 为您提供便于实施的宏。这可以在您自己没有宏的情况下轻松完成。
  • 我试图更好地理解可变长度参数以及操作系统如何在堆栈上处理它们。你能把我链接到一个例子 spin_eight/
  • 不涉及操作系统。

标签: c printf


【解决方案1】:

在C Reference Manual by Dennis M. Ritchie 中查看早在... 和<stdarg.h> 之前就存在的printf() 的实现:

printf ( fmt, args )
  char fmt [ ] ;
{
  ...
  int *ap, x, c ;
  ap = &args ; /* argument pointer */
  ...
  for ( ; ; ) {
    while ( ( c = *fmt++ ) != ´%´ ) {
      ...
      switch ( c = *fmt++) {
      /* decimal */
      case ´d ´:
        x = *ap++ ;
        if(x < 0) {
          x = -x;
          if ( x<0 ) { /* is - infinity */
            printf ( "-32768" ) ;
            continue ;
          }
          putchar ( ´-´);
        }
        printd(x);
        continue ;
      ...
      }
      ...
    }
    ...
  }
}

printd(n)
{
  int a ;
  if ( a=n/10 )
    printd(a);
  putchar ( n%10 + ´0´ ) ;
}

您可以忽略函数和参数声明的旧 (AKA K&R) 语法:

printf ( fmt, args )
  char fmt [ ] ;

甚至用更现代的替换它:

int printf ( char fmt[], int args )

但想法是一样的,您可以直接获得指向第一个可选参数 (args) 的指针,就像在上面的代码中使用 ap = &amp;args; 所做的那样,然后继续递增它以访问更多参数。

或者你可以间接地这样做,使用最后一个非可选参数作为起点:

int printf ( char fmt[], ... )
{
  ...
  int *ap, x, c ;
  ap = &fmt ; /* argument pointer */
  ap++; /* ap now points to first optional argument */
  ...
}

这说明了机制。

请注意,如果您这样编写代码,它将无法移植,甚至可能无法与您的编译器一起工作。

【讨论】:

  • 这不是只适用于 32 位系统,而不适用于 64 位系统吗?你如何让它与 64 位系统一起工作?您是否必须使用特殊标志强制它以 32 位格式运行?
  • 这取决于系统的种类。如果指针和整数的大小相同,它将适用于 16 位、32 位和 64 位以及任何系统。
  • 它不适用于不一定在堆栈上以相反顺序传递参数的架构。允许在寄存器中传递参数的平台 ABI,或者堆栈向前而不是向后增长的平台将不起作用。
猜你喜欢
  • 2017-02-06
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
  • 1970-01-01
  • 2012-12-25
  • 1970-01-01
  • 2020-06-05
  • 2011-01-01
相关资源
最近更新 更多