ページ 1 / 1
可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月25日(水) 02:44
by あまぞん
#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
***************************
みたいな感じに表示させたいです。
できればですが、なぜエラーになるか教えてほしいです。
いろいろすみません。。。
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月25日(水) 08:56
by toyo
引数の個数を渡さないと引数が何個あるかを関数側では知ることが出来ませんよ
#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);
}
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月25日(水) 09:02
by non
>引数の個数を渡さないと引数が何個あるかを関数側では知ることが出来ませんよ
もしくは、リストの最後に終わりの印をつけることですね。例えば9999とか
sub("abc",4,9,6,9999);
"abc"は使ってないけど何?ここをprintfのように
"%d%d%d"みたいにして個数を知ることもできますね。
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月25日(水) 09:07
by toyo
nonさんの回答を見てひょっとして
va_start(va,a);
for (i = 0;a != '\0';i++){
みたいなことがやりたかったのでしょうか
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月25日(水) 09:24
by non
ああ、なるほど。。。。。
"abc"ってそういうことですか?
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月25日(水) 09:47
by 初級者
可変長引数を指定できる代表格のprintf関数で
引数の個数を渡さずにすんでいることから見て、「引数の個数が必要」という指摘は的はずれだと思います。
それよりは、3バイト確保した領域に
"abc" という、終端の '\0' を含む4バイトを渡している方が
よほど問題かと。
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月25日(水) 10:07
by Mist
> 引数の個数を渡さずにすんでいることから見て、「引数の個数が必要」という指摘は的はずれだと思います。
そんなことはないです。
printfは例えば"%d %d\n"のように書式指定文字列の内容から引数の個数を判断しています。
va_argは引数の数以上に実行すると予測しないエラーを起こすため今回のようなやり方をする場合は引数の個数は必要です。
nonさんがおっしゃられているように終りがわかる印を付けるなどしなければならないでしょう。
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月25日(水) 10:18
by Mist
ためしに以下のようなプログラムを組んでみてください。
int main(void) {
printf("%d %d\n", 10);
return 0;
}
コンパイルエラーにはならず、2個目は不定値が表示されます。
つまり、実際に渡した引数は1個ですがprintfは渡された引数は2個だと判断して動作しています。
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月25日(水) 12:03
by toyo
関数の引数の char a[ 3 ] は char* a になるので実害はないですよね
可変引数は型と個数が合わないとバグになるし関数側で型を知ることが出来ないのであまりよくないんですよね
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月25日(水) 12:28
by 初級者
私のようなうつけ者が差し出がましいことを申しまして失礼しました。
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月26日(木) 09:15
by 通りすがり
みんなミスリーディングされすぎです。
可変長引数とか関係ないよ。
int b に対して bなんてやってるから文句言われてるだけでしょ。
Re:可変長引数を表示するプログラムでのコンパイルエラー
Posted: 2009年2月26日(木) 13:32
by TOMONORI
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参照)。