• ベストアンサー

引数の数が可変な関数

C言語の関数でいつも不思議に思うのですが printf("%sさんの成績は、%d点です。", name, score); printf("\n\n"); のように引数が可変な関数を作成したいのですが、どうすればよいでしょうか? CとC++の両方の書き方が知りたいです。 理解したいの解説している書籍なども探しています。

質問者が選んだベストアンサー

  • ベストアンサー
  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.2

>なぜですか? 何故かは人によりけりだと思いますが、 C言語での実装上、引数はスタックに順に並んでいること になっていますが可変引数とはこれをマクロを使ってポインタ 計算しそれぞれの引数をvoid*型のデータとみなして分解するので いろんな意味で危険だったりします。 ほかにも、型のサイズなんかによって落とし穴が多い #特にC++と混ざるとオブジェクトの型やサイズは計算しづらく #可変引数はその型を知る方法も実装依存になる ので理解して無理に使うより、そもそも本当に可変で実装しないと いけないか実装を見直すほうが良いかと。 #実際私は、デバッグ用のログや文字列とかを出力したりするくらいにしか使ったこと無いです。。。

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

可変長引数は危険ですからねぇ. 特に, コンパイラで型チェックや自動的な型変換ができないのが痛い. printf とか scanf ではまるというのはよくある光景です. まあ, 「無理に使うのは理解できていないからだ」とは思いますが>#2, 覚えたてだと使いたがるかも.

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.1

"C 可変引数"でググった http://www.geocities.jp/ky_webid/c/057.html ほかにもいっぱいある。 でも使わない方が良い。

tobasu
質問者

補足

>でも使わない方が良い。 なぜですか? 以下の理由だからですか? >va_start>とva_endマクロの呼び出しは忘れないように注意して下さい。忘れると動作がおかしくなり、最悪の場合、プログラムが強制終了します。

関連するQ&A

  • 可変個引数の関数

    今現在可変個引数をとる関数を作成しています。 物としてはprintfと同等のものなのですが、可変個引数の取得の方法がわからず停滞してしまっています。 printtest("%s",str); と記述してstrの中身が出力されるようにしたいのです。 どうかご助力のほどよろしくお願いいたします。

  • 可変引数???

    昔作った記憶はあったのですが、具体的にどうすれば良いか忘れてしまい 詳しい方にお聞きしたいのですが、 printf("data=%d, result=%d, msg=%s\n", data, result, msg); のように書式設定できる可変引数?できるような関数(↓)を作りたいです。 test(100, "XXXX", "data=%d, result=%d, msg=%s\n", data, result, msg); VC2005や C#では使わない方が良い?のでしょうか。

  • 可変長引数関数のマクロ関数について

    可変長引数をとる関数をマクロで置き換えたいのですが、 この方法だとできません。うまく実現できないでしょうか? ------------------------------------------------------- #define TRACE(arg, ...) trace(__FILE__,__LINE__,arg, ...) void trace(char *file, int line, char *arg, ...) {   ...(略)... } func() {   ...   TRACE("hello %s", "taro");   ... } ------------------------------------------------------- よくあるトレース処理だと思いますがこんな感じです。 他にも代替手段は考えつきますが、 可変長引数の関数のマクロが可能かが知りたいです。 どなたがご存知の方がいらっしゃいましたら、よろしくお願いします。

  • sprintf関数の作り方

    c言語にsprintf関数っていうのがありますが、 これはどうやって作るのでしょうか? sprintf関数は引数の数が可変であり、引数のデータ型 が様々なので、いったいどうやって作るのか知りたいです。 どこかにソースでもあればいいのですが・・・。

  • AVERAGEIFS関数の引数が可変の場合

    averageifs関数のことについて教えてください。   引数の合計対象範囲をindirect関数とaddress関数、match関数を使い可変にしています。 条件範囲また条件はダイアログボックスで確認する限り計算されてはいるのですが、 戻り値が#VALUEになります。 どうすればキチンと戻り値が表示されるのでしょうか? ちなみに可変の部分(合計対象範囲)をaverage関数で計算するとちゃんと計算されています。          ↓こんな式です。    AVERAGEIFS(INDIRECT(ADDRESS(MATCH(DATE(データ!$D$1,$A3,1),データ!$D:$D,0),6,,,"データ")):INDIRECT(ADDRESS(MATCH(DATE(データ!$D$1,$A3+1,0),データ!$D:$D,0),6,,,"データ")),データ!$C:$C,0) ややこしいですが、お願いします。

  • 引数の可変

    覚えたての引数の可変を使ってみた素人であります。(独学です 見よう見真似で書いた為、目茶苦茶だと思われます。 自分で簡単なexeファイルを作ってみていて 引数の可変が必要となったので付け足そうとしていたのですが、「引数の可変」部の他 意外にもfor文からもエラーが出ました(while使えば済む話なのですが) 今までfor文をあまり使わずwhile文ばかり使っていた為、for文の基本的な構文が失敗しているのかもしれません。折角だから使ってみようとした結果がこれです。 #include <stdio.h> #include <locale.h> #include "DxLib.h" #include <string.h> #include <stdarg.h> int i; ・・・略・・・ class CharsOut{ ____int ypixel; ____char *hangar; ____int size; ____int HowMany; ____int list; public:   ____int CharsOuting(int HowMany,int ypixel,int size,...); }; int CharsOuting(int HowMany,int ypixel,int size,...){ ____va_start(list,HowMany); ____for (i=0;i<HowMany;i++){ ________printf("%s",va_arg(list,char *)); ____} ____va_end(list); ____return 0; } ypixel、size...といった変数等は気にしないでください。 成功していたらコードを足すつもりでした。 自分がやりたいことは、main関数から変数HowMany,*hangar等を受け取り 文字列*hangarを引数の分出力したいのであります。引数の可変は*hangarを何個か渡すつもりだったので使用しました。 こんな感じに使うつもりでしたc.CharsOuting(2,0,32,"I am ", "hangury"); ※リストは(int HowMany,int ypixel,int size,...)です ※ハングリーのスペルが違う等ということはとてつもなくどうでもいいことなのです。 自分で「main関数から*hangarを受け取り」と書いておきながらリストに*hangarがない時点でおかしいと思ってはいるのですが、記述の方法が分からないので書けません。 以下エラー (名前とか一部改変・不要な部分省略 1>------ ビルド開始: プロジェクト:(≡ω≡.), 構成: Debug Win32 ------ 1>コンパイルしています... 1>soucer.cpp 1>error C2040: 'i' : 'int' は 'int [5]' と間接操作のレベルが異なります。 1>error C2065: 'list' : 定義されていない識別子です。 1>error C2440: '=' : 'int' から 'int [5]' に変換できません。 1>配列型への変換はありませんが、参照またはポインタから配列への変換があります。 1>error C2446: '<' : 'int' 型から 'int *' 型への変換ができません。 1>整数型からポインタ型への変換には reinterpret_cast、C スタイル キャストまたは関数スタイル キャストが必要です。 1>error C2040: '<' : 'int [5]' は 'int' と間接操作のレベルが異なります。 1>error C2105: '++' には左辺値が必要です。 1>error C2065: 'list' : 定義されていない識別子です。 1>error C2065: 'list' : 定義されていない識別子です。 1>ビルドログは "file://c:\・・・\Debug\BuildLog.htm" に保存されました。 1>(≡ω≡.) - エラー 8、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== 文章能力なくて申し訳ありません。 ご回答頂ければ幸いであります。宜しくお願いします。 OS:WinXP コンパイラ:Visual C++

  • 可変長引数関数の引数の文字列サイズを取得したい

    以下のような可変長の文字列を受け取れる関数があったとします。 ...の部分で引数を受け取ることが可能ですが、この場合引数の文字列サイズを 知ることは可能なのでしょうか? 関数を呼び出してみて例を挙げるとするなら、  GetArgs( "%s", "あいうえお" ); この「あいうえお」の部分の文字数をGetArgs内で知りたいのです。 void GetArgs( char * FormatString, ... ) {   va_list VaList;   va_start( VaList, FormatString );   // ここでFormatStringの引数の文字列サイズを取得したい   va_end( VaList ); }

  • printf()関数の第一引数の文字列のアドレスを知りたいんですが。

    C言語を色々試して実験中です。 たとえば、 printf("あなたは100歳です\n");  という文をprintf関数で出力するとすると、この文字列定数「あなたは100歳です」のアドレスを調べたいんです。調べる事はできますか?よろしくお願いしますm(_ _)m

  • 関数の引数表記なしについて

    はじめまして。C言語初心者です。 質問させてください。 関数を宣言して引数を表記しないで使用することは可能なのでしょうか? またどのような場合に使用するのでしょうか? 例として以下コードになります。 ----------------------- #include<stdio.h> int test1(int a); void test2(int b); void main(){ int i = 0; int j = 0;       //この部分 i = test1; printf("%d\n", i);        //この部分 j = test2; printf("%p\n", j); } int test1(int a){ return a + 1; } void test2(int b){ printf("test"); } --------------------------- 出力結果を見ると関数のアドレスが帰ってくるように思われますが、詳細が分かりません。 詳しい方がいらしましたら教えてください。 宜しくお願いいたします。

  • 引数に二重配列のある関数について

    void calc(int *a,int b,int c){ a[0]=b+c; a[1]=b-c; } void main(void){ int x[2]; int y=2,z=5; calc(x,y,z); printf("x[0]=%d,x[1]=%d\n",x[0],x[1]); } 上のように引数が普通の配列の関数ならできるのですが, 引数が下のような多重配列になるとエラーが出てしまいできません。 void keisan(int **a,int b,int c){ a[0][0]=b+c; a[0][1]=b-c; a[1][0]=b*c; a[1][1]=b/c; } void main(void){ int x[2][2]; keisan(x,6,2); printf("x[0][0]=%d,x[0][1]=%d\n",x[0][0],x[0][1]); printf("x[1][0]=%d,x[1][1]=%d\n",x[1][0],x[1][1]); } 引数に多重配列を使った場合の関数の作り方について教えてください. お願いいたします.