可変長引数を表示するプログラムでのコンパイルエラー

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
あまぞん

可変長引数を表示するプログラムでのコンパイルエラー

#1

投稿記事 by あまぞん » 16年前

#include <stdio.h>
#include <stdarg.h>

void sub(char a[3],int b, ...);

int main(void)
{
	sub("abc",4,9,6);
	
	return 0;
}

void sub(char a[3],int b, ...)
{
	va_list va;
	int i;
	
	va_start(va,b);
	
	for (i = 0;b != '\0';i++){ /*ここのb != '\0'がいけないんだと思う*/
		printf("%d\n",va_arg(va,int));
	}
	
	va_end(va);
}


エラーメッセージ
エラー E2062 va_arg.c 20: 無効な間接参照(関数 sub )

使用OS:Windows XP SP3
使用コンパイラ:borland C++ Compiler

タイトルの通り、可変長引数を表示したいのですが、うまく表示できません。
***************************
4
9
6
***************************
みたいな感じに表示させたいです。

できればですが、なぜエラーになるか教えてほしいです。
いろいろすみません。。。

toyo

Re:可変長引数を表示するプログラムでのコンパイルエラー

#2

投稿記事 by toyo » 16年前

引数の個数を渡さないと引数が何個あるかを関数側では知ることが出来ませんよ
#include <stdio.h>
#include <stdarg.h>

void sub(char a[3],int num, ...);

int main(void)
{
	sub("abc",3,4,9,6);
	
	return 0;
}

void sub(char a[3],int num, ...)
{
	va_list va;
	int i;
	
	va_start(va,num); /* numは引数の個数 */
	
	for (i = 0;i < num;i++){
		printf("%d\n",va_arg(va,int));
	}
	
	va_end(va);
}

non

Re:可変長引数を表示するプログラムでのコンパイルエラー

#3

投稿記事 by non » 16年前

>引数の個数を渡さないと引数が何個あるかを関数側では知ることが出来ませんよ

もしくは、リストの最後に終わりの印をつけることですね。例えば9999とか
sub("abc",4,9,6,9999);
"abc"は使ってないけど何?ここをprintfのように
"%d%d%d"みたいにして個数を知ることもできますね。

toyo

Re:可変長引数を表示するプログラムでのコンパイルエラー

#4

投稿記事 by toyo » 16年前

nonさんの回答を見てひょっとして
va_start(va,a);
	
	for (i = 0;a != '\0';i++){

みたいなことがやりたかったのでしょうか

non

Re:可変長引数を表示するプログラムでのコンパイルエラー

#5

投稿記事 by non » 16年前

ああ、なるほど。。。。。
"abc"ってそういうことですか?

初級者

Re:可変長引数を表示するプログラムでのコンパイルエラー

#6

投稿記事 by 初級者 » 16年前

可変長引数を指定できる代表格のprintf関数で
引数の個数を渡さずにすんでいることから見て、「引数の個数が必要」という指摘は的はずれだと思います。

それよりは、3バイト確保した領域に
"abc" という、終端の '\0' を含む4バイトを渡している方が
よほど問題かと。

Mist

Re:可変長引数を表示するプログラムでのコンパイルエラー

#7

投稿記事 by Mist » 16年前

> 引数の個数を渡さずにすんでいることから見て、「引数の個数が必要」という指摘は的はずれだと思います。

そんなことはないです。
printfは例えば"%d %d\n"のように書式指定文字列の内容から引数の個数を判断しています。
va_argは引数の数以上に実行すると予測しないエラーを起こすため今回のようなやり方をする場合は引数の個数は必要です。
nonさんがおっしゃられているように終りがわかる印を付けるなどしなければならないでしょう。

Mist

Re:可変長引数を表示するプログラムでのコンパイルエラー

#8

投稿記事 by Mist » 16年前

ためしに以下のようなプログラムを組んでみてください。
int main(void) {
    printf("%d %d\n", 10);

    return 0;
}
コンパイルエラーにはならず、2個目は不定値が表示されます。
つまり、実際に渡した引数は1個ですがprintfは渡された引数は2個だと判断して動作しています。

toyo

Re:可変長引数を表示するプログラムでのコンパイルエラー

#9

投稿記事 by toyo » 16年前

関数の引数の char a[ 3 ] は char* a になるので実害はないですよね
可変引数は型と個数が合わないとバグになるし関数側で型を知ることが出来ないのであまりよくないんですよね

初級者

Re:可変長引数を表示するプログラムでのコンパイルエラー

#10

投稿記事 by 初級者 » 16年前

私のようなうつけ者が差し出がましいことを申しまして失礼しました。

通りすがり

Re:可変長引数を表示するプログラムでのコンパイルエラー

#11

投稿記事 by 通りすがり » 16年前

みんなミスリーディングされすぎです。
可変長引数とか関係ないよ。

int b に対して bなんてやってるから文句言われてるだけでしょ。

TOMONORI

Re:可変長引数を表示するプログラムでのコンパイルエラー

#12

投稿記事 by TOMONORI » 16年前

char a[3] → const char *
として下さい。
それからbの値は通常引数の数を格納するものなので、vaはbの次の要素から
ポイントします。構造上bの値は引数の数でなければならないという制限は無い為
無視しても動くことは動きます。しかしそのコードはよーく隠して下さい。
渡された引数はいったん何らかのコンテナ(今回ならベクタで十分)に格納すると
良いと思います。
#include <stdio.h>
#include <stdarg.h>
#include <vector>

void sub(const char *, int b, ...);

int main()  // Cではないのでvoidは書かない
{
  sub("abc", 1, 9, 6);
				
  return 0;
}

void sub(const char * s, int b, ...)
{
  va_list va;
  va_start(va, b);

  std::vector<int> v;
  v.push_back(b);
  while(v.size() < sizeof(s) - 1)  // 改行コードの分-1
  {
    v.push_back(va_arg(va, int));
  }

  for(std::vector<int>::iterator i = v.begin();
      i < v.end();
      ++ i)
  {
    printf("%d\n", *i);  //! std::coutの方が柔軟
  }
}
可変長引数の型は組み込み型以外は未定義っぽいので気をつけて下さい。
逆に組み込み型なら安全に動作するらしいです(JISX3010参照)。

閉鎖

“C言語何でも質問掲示板” へ戻る