3

スタックをチェックして可変長引数関数を処理する方法を理解し、実装しようとしていますが、どこからどのように開始すればよいかわかりません。次のリンクが役立つことがわかりましたが、印刷機能のようなもののために c でこのようなことができる方法をまだよく理解していません。

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

C++ の関数引数リスト内の末尾のドット (...)

4

1 に答える 1

6

ずっと前に存在していたC Reference Manual by Dennis M. Ritchie実装を見てください:printf()...<stdarg.h>

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´ ) ;
}

関数とパラメーター宣言の古い(別名K&R)構文は無視できます。

printf ( fmt, args )
  char fmt [ ] ;

そしてそれをより現代的なものに置き換えさえします:

int printf ( char fmt[], int args )

ただし、考え方は同じですargs。上記のコードで.を使用して行われるように、最初のオプションの引数()へのポインターを直接ap = &args;取得し、それをインクリメントし続けて、さらに引数にアクセスできるようにします。

または、オプションではない最後の引数を開始点として使用して、間接的に行うこともできます。

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

これはメカニズムを示しています。

このようにコードを書くと、移植性がなくなり、コンパイラで動作しなくなる可能性があることに注意してください。

于 2013-03-05T07:05:42.863 に答える