可変引数とは? わかりやすく解説

可変長引数

(可変引数 から転送)

出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2025/04/07 14:37 UTC 版)

可変長引数(かへんちょうひきすう、: variable length argumentsvariadic arguments)とはプログラミング言語において、関数(サブルーチンメソッドを含む)やマクロ引数が固定ではなく任意の個数となっている引数のことである。 可変引数可変個引数とも呼ばれる。

可変長引数を持つ関数を可変長引数関数: variadic function)と言う。

いくつかの言語では型安全が保証されなくなるので注意が必要である。

手法

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

  • C言語 - 標準Cライブラリに用意されているstdarg.h英語版を使う。仮引数に型の指定は特に行わない。
  • C# - 配列型の仮引数の直前にparamsキーワードを指定する。
  • Java - 仮引数の型名と仮引数名の間に ... を記述する。実引数は配列に格納され、型には制限が付く。J2SE 5.0で追加された機能。Javaの文法#可変引数を参照。
  • JavaScript - argumentsオブジェクトを利用する。
  • Perl - サブルーチンに固定の仮引数を指定することはできない。どんなサブルーチンでも引数はリスト変数 @_ を通して動的に受け取る以外に方法がない。
  • Python - 仮引数名の前に*あるいは**を付けてアクセスする。
  • Common Lisp - &rest に続けてリストを受け取る仮引数名を指定する。
  • Scheme - . に続けてリストを受け取る仮引数名を指定する。
  • Visual Basic for Applications - ByVal/ByRefの代わりにParamArrayを指定する。

C言語

C言語においては printfscanf といった標準ライブラリの関数が可変長引数をとる代表例である。可変長引数をとる関数のユーザー定義も可能である。信頼できない入力を扱う場合は書式文字列攻撃に注意する必要がある。可変長引数として渡す際に型情報が失われるため、型に関する情報を別途渡すなどする必要がある。

倍精度浮動小数点数の平均値を求める関数average_of_doublesの例を考える。

#include <assert.h>
#include <stdarg.h>
/* stdarg.h には、マクロ va_start、va_arg、va_end が定義されている。対応する va_start と va_end の呼び出しは、同じ関数内でなければならない。 */

double average_of_doubles(int count, ...) {
  va_list ap;
  double sum = 0;
  int i;
  assert(count > 0);
  va_start(ap, count); /* スタック変数のアドレスを参照するため、最後の引数が必要である。 */
  for (i = 0; i < count; ++i) {
    /* スタックに積まれているはずの double 型の値を取り出し、ポインタ変数 ap が次の引数を指すように変更する。 */
    sum += va_arg(ap, double);
  }
  va_end(ap);
  return sum / count;
}

上記を呼び出すコード例は次の通りである。データの個数を最初の引数として与えている。

#include <stdio.h>

int main(void) {
  double average1 = average_of_doubles(3, 1.0, 2.0, 3.0);
  double average2 = average_of_doubles(4, 1.5, 2.1, -3.0, 0.7);
  printf("%f\n", average1);
  printf("%f\n", average2);
  return 0;
}

Cの可変長引数には、「既定の実引数拡張」(default argument promotion) と呼ばれる暗黙の型変換規則が適用される[注釈 1][注釈 2]。例えばfloat型の実引数は、double型に拡張される。関数形式マクロva_arg()を使ってスタックから値を取り出す際、指定した型の値が実際には格納されていなかった場合、未定義動作を引き起こす。

上記の例では、可変長引数にdouble型の値(または既定の実引数拡張を受けるfloat型の値)が渡されることを想定しているが、可変長引数に間違ってintなどの整数型の値を渡してもコンパイルは通ってしまい、未定義動作を引き起こす。この例では同じdouble型の1つ以上の値を渡すことができればよいので、可変長引数を使うのではなく、単純にdouble配列を使って型安全に実装すべきである。

double average_of_doubles(const double* values, int count) {
  double sum = 0;
  int i;
  assert(values);
  assert(count > 0);
  for (i = 0; i < count; ++i) {
    sum += values[i];
  }
  return sum / count;
}

Cプリプロセッサ・マクロ

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

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

void realdbgprintf(const char *sourceFilename, int sourceLineNumber, const char *formatString, ...);

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

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

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

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

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

gcc以外でも使用するためには__VA_ARGS__を使うほかないが、その場合は書式文字列も含めて可変長引数として渡す必要がある。

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

Microsoft Visual C++の独自拡張モードでは、ゼロ個の引数を受け取る__VA_ARGS__は末尾コンマを抑制する動作をする[3]

C++20では、空の可変引数を処理するための__VA_OPT__マクロをサポートする[4]

C++

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

template<typename... Args> class tuple;

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

tuple<std::vector<int>, std::map<std::string, std::vector<int>>> someTuple; // tuple インスタンス。
tuple<> emptyTuple;

std::tupleとしても標準化されている。

また、C++11ではC99との互換性向上のため、可変長引数マクロが標準化された (N1653)。

Java

平均値を求める静的メソッド average の例を考える。平均値の計算には最小でも1個の値が必要であるから、固定個数の仮引数(必須の仮引数)として x0 を指定しており、それ以降を任意個数の引数としている。任意個数の値は仮引数 xsdouble 型の配列として格納される。

static double average(double x0, double ... xs) {
  double sum = x0;
  int count = 1;
  for (double x: xs) {
    sum += x;
    ++count;
  }
  return sum / count;
}

上記を呼び出すコード片の例は次の通りである。

System.out.println(average(0.3, 9.4, 5.2, 4.5, 9.7));

Scheme

平均値を求める手続き average の例を考える。平均値の計算には最小でも1個の値が必要であるから、固定個数の仮引数(必須の仮引数)として x を指定しており、それ以降を任意個数の引数としている。任意個数の値は仮引数 xs にリストとして格納される。

(define (average x . xs)
  (/ (apply + x xs) (+ 1 (length xs))))

上記を呼び出すコードの例は次の通りである。

(average 0.3 9.4 5.2 4.5 9.7)
 5.82

英語

variadicは「可変長引数の」「可変個引数の」という意味の形容詞である。C言語などでは可変長引数のことを「variable argument」と呼ぶ。辞典などでは直訳して「変数引数」とされていることがあるが、これは誤訳である。なお、「変数引数」という言葉は、Pascalなどで変数渡しに使用される「variable parameter」の定訳であり、これは可変長引数とは違うものを指す。したがって、可変長引数のことを「変数引数」と呼ぶのは混乱の原因となる。

脚注

注釈

  1. ^ 例えばCの国際規格ISO/IEC 9899:1999またはその翻訳であるJIS X 3010:2003を参照のこと。
  2. ^ C++の国際規格ISO/IEC 14882:2003の翻訳であるJIS X 3014:2003では、「既定の実引数昇格」と呼ばれているが、同じものである。

出典

  1. ^ : variadic macro
  2. ^ マクロ呼び出しにおいて余計なカッコを付けておくことで、カッコとコンマを含むような文字列そのものをマクロ引数に対応させる。
  3. ^ Variadic macros | Microsoft Docs
  4. ^ 可変引数が空でない場合のトークン置換 - cpprefjp C++日本語リファレンス
  5. ^ : variadic template

関連項目


可変引数

出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2022/05/08 02:09 UTC 版)

Javaの文法」の記事における「可変引数」の解説

Java SE 5.0において、引数個数可変あるようメソッドについての文法上の便宜 (varargs) が追加された。これによって引数個数可変であるメソッドタイプセーフ使用することが容易になる最後パラメタの後に「...」と書くと、Java全ての引数配列格納するpublic void drawPolygon(Point... points) { /* ... */ } このメソッドを呼ぶ際、プログラマ個々pointsを単にカンマ区切って書けばよく、Pointオブジェクト配列をわざわざ用意する要はない。このメソッド内部points参照する際はpoints[0]、points[1]、などのように書ける。points渡されていない場合配列lengthは0となる。可変個の引数別に固定的必要なパラメタがある場合は、それらのパラメタは可変引数に先立って指定すればよい。 // ポリゴン少なくとも3つの点を必要とする。public void drawPolygon(Point p1, Point p2, Point p3, Point... otherPoints) { /* ... */ }

※この「可変引数」の解説は、「Javaの文法」の解説の一部です。
「可変引数」を含む「Javaの文法」の記事については、「Javaの文法」の概要を参照ください。

ウィキペディア小見出し辞書の「可変引数」の項目はプログラムで機械的に意味や本文を生成しているため、不適切な項目が含まれていることもあります。ご了承くださいませ。 お問い合わせ


英和和英テキスト翻訳>> Weblio翻訳
英語⇒日本語日本語⇒英語
  

辞書ショートカット

すべての辞書の索引

「可変引数」の関連用語

可変引数のお隣キーワード
検索ランキング

   

英語⇒日本語
日本語⇒英語
   



可変引数のページの著作権
Weblio 辞書 情報提供元は 参加元一覧 にて確認できます。

   
ウィキペディアウィキペディア
All text is available under the terms of the GNU Free Documentation License.
この記事は、ウィキペディアの可変長引数 (改訂履歴)の記事を複製、再配布したものにあたり、GNU Free Documentation Licenseというライセンスの下で提供されています。 Weblio辞書に掲載されているウィキペディアの記事も、全てGNU Free Documentation Licenseの元に提供されております。
ウィキペディアウィキペディア
Text is available under GNU Free Documentation License (GFDL).
Weblio辞書に掲載されている「ウィキペディア小見出し辞書」の記事は、WikipediaのJavaの文法 (改訂履歴)の記事を複製、再配布したものにあたり、GNU Free Documentation Licenseというライセンスの下で提供されています。

©2025 GRAS Group, Inc.RSS