可変長引数

出典: フリー百科事典『ウィキペディア(Wikipedia)』
ナビゲーションに移動 検索に移動

可変長引数(かへんちょうひきすう)とはプログラミング言語において、関数やメソッドやマクロの引数が固定ではなく任意の個数となっている引数のことである。可変引数可変個引数とも呼ばれる。そのような関数を可変長引数関数[1]と言う。いくつかの言語では型安全が保証されなくなるので注意が必要である。

手法[編集]

可変長引数を取る手続きメソッド、は、多くのコンピュータプログラミング言語でサポートされている。

  • C言語 - stdarg.h(stdarg.h英語版)を使う。仮引数に型の指定は特に行わない。
  • C# - 配列型の仮引数の直前にparamsキーワードを指定する。
  • Java - ...という記法を使う。実引数は配列に格納され、型には制限が付く。Javaの文法#可変引数を参照。
  • Javascript - argumentsオブジェクトを利用する。
  • Python - 仮引数名の前に*あるいは**を付けてアクセスする。

[編集]

C言語[編集]

C言語においては printfscanf といった標準ライブラリの関数が可変長引数をとる。可変長引数をとる関数のユーザー定義も可能である。信頼できない入力を扱う場合は書式文字列攻撃に注意する必要がある。

#include <stdarg.h>
/* stdarg.h には、マクロ va_start、va_arg、va_end が定義されている。 */

double average (int count, ...)
  {
  va_list ap ;
  double sum = 0;
  va_start(ap, count) ; /* スタック変数のアドレスを参照するため、最後の引数が必要である。 */
  for (int i=0 ; i<count ; ++i)
    {sum += va_arg(ap, double) ;} /* ポインタ変数 ap が次の引数を指すように変更する */
  va_end(ap) ;
  return sum / count ;
  }

Cプロプロセッサ・マクロ[編集]

C言語のプリプロセッサのマクロ定義において、可変長引数マクロ[2]には、以前はトリック的な方法[3]が使われていたが、C99で本物の可変長引数マクロが標準化された。__VA_ARGS__という識別子を使用する。

次のような関数の呼出しに展開されるマクロを定義したいとする。関数が可変長引数をとるため、機能を制限したくなければ、マクロも可変長引数をとるようにしたい。

void realdbgprintf (const char *SourceFilename, int SourceLineno, const char *CFormatString, ...);

C++での可変長引数マクロの設計に問題があるため以下に示すような定義は行えない。

#define dbgprintf(cformat, ...) realdbgprintf (__FILE__, __LINE__, cformat, __VA_ARGS__)

この書き方はdbgprintf("Hello")と記述した際にrealdbgprintf (__FILE__, __LINE__, "Hello", )と展開される。関数の引数リストをカンマで終えると構文エラーを起こすため、printfのような使い勝手は得られない。

gccの独自構文では##__VA_ARGS__という識別子もサポートしている。これを利用することにより引数が0のものも定義できる。

#define dbgprintf(cformat, ...) realdbgprintf (__FILE__, __LINE__, cformat, ##__VA_ARGS__)

gcc以外でも使用するためには__VA_ARGS__を使うほかないが、その場合は少々トリッキーな書き方となる。

#define dbgprintf(...) realdbgprintf (__FILE__, __LINE__, __VA_ARGS__)

C++[編集]

可変長引数テンプレート[4]C++11でサポートされた。

template<typename... Values> class tuple;

このtupleクラステンプレートは、 テンプレート引数としていくらでも型名を取れる:

class tuple<std::vector<int>, std::map<std::string, std::vector<int> > >someInstanceName;
class tuple<> emptyTuple;

英語[編集]

C言語などで「variable argument」と呼ぶため、直訳的に「変数引数」とされていることがあるが、これは誤訳であり、Pascalなどで可変長引数とは違うものを指す「variable parameter」の定訳であるから、可変長引数のことを「変数引数」と呼ぶのは混乱の原因である。

脚注[編集]

  1. ^ 英語: variadic function
  2. ^ : variadic macro
  3. ^ マクロ呼出しにおいて余計なカッコを付けておくことで、カッコとカンマを含むような文字列そのものをマクロ引数に対応させる。
  4. ^ : variadic template

関連項目[編集]