ページ 11

引数が配列の場合の処理

Posted: 2009年5月30日(土) 20:11
by チルチル
void data(int data[2]){



}

のような関数に引数を渡したいんですが

色々試した結果

int a[2]={1,2};

data(a);

もしくは

data(0);

という方法でしかコンパイルを通りませんでした

0の場合は数値が必要ない場合だから問題ないんですが

数値が必要な場合は2行にすると見栄えが悪いので

関数の()の中で値を渡す方法はないでしょうか?

Re:引数が配列の場合の処理

Posted: 2009年5月30日(土) 20:28
by box
> void data(int data[2]){
> のような関数に引数を渡したいんですが

data[/url]という配列全体を渡したい(はずな)のに、

> data(0);

こんな風に即値だけを渡すのは、したいこととしていることとがマッチしていない、
ということですね。
渡した値ゼロをNULLポインタとみなし、コンパイルは通るかもしれませんが、
実行時にどうなるかは…。

> data(a);
> 関数の()の中で値を渡す方法はないでしょうか?

この方法は、「配列の先頭要素のアドレス」という「値」を
渡している、正しい方法です。
配列の要素数も渡す方がよいとは思いますけれど…。

Re:引数が配列の場合の処理

Posted: 2009年5月30日(土) 20:32
by たかぎ
次のようにします。
data((int[2]){ 1, 2 });
ただし、最新の規格に対応していないコンパイラでは、この方法は使えない可能性があります。

Re:引数が配列の場合の処理

Posted: 2009年5月30日(土) 21:02
by チルチル
残念、使えませんでした・・

ちなみにdata関数は例えばの場合で

実際は弾を登録する関数の沢山ある引数の最後に加える予定の引数です

弾の構造体の使わない時が多い配列に代入する値を渡します

なので使わない時は0でOKです

まあ配列だから全部0になるんじゃないかな~

と思ったらフリーズしました・・

使わなければ問題無いとは思いますが・・

Re:引数が配列の場合の処理

Posted: 2009年5月31日(日) 05:40
by box
> と思ったらフリーズしました・・

何をしたときにフリーズしましたか?
実行時ですか?

ある関数の引数を配列として、その関数を呼び出しただけで
フリーズするとはちょっと考えにくいです。

もしかすると別の所に原因があるかもしれません。
そこで、関係しそうな箇所のソースを公開するお気持ちはありますか?

Re:引数が配列の場合の処理

Posted: 2009年5月31日(日) 12:42
by チルチル
あ~すいません説明不足でした
#include "DxLib.h"

int a;

void data(int data[2]){

	a=data[0];

}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);SetOutApplicationLogValidFlag( FALSE );
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

data(0);

DxLib_End();
return 0;

}
引数になっている変数を呼び出すだけなら動くんですが
その変数で代入とか比較とかをやるとフリーズするようですね

これだと条件分岐ができませんからやっぱり無理ですね・・
引数の初期化とかも無理でしたし・・

でも引数がNULLにできる関数は沢山ありますよね
一体どうなっているんでしょうか・・

Re:引数が配列の場合の処理

Posted: 2009年5月31日(日) 13:26
by KEYONN_
2次元配列が引数の関数に値を渡す時は、
int Tbl[300][20]={0};

int ArrayProc(Tbl[/url][20])
{
    //処理
    return 0;
}
でいけます。

Re:引数が配列の場合の処理

Posted: 2009年5月31日(日) 13:41
by MNS
引数に0を渡したということは、
NULLポインタを渡したこととなりますから、
data[0]が指す先のアドレスはNULLになります。
ですので、data[0]へアクセスしようとすると
フリーズするのは、別におかしくはないはずです。

Re:引数が配列の場合の処理

Posted: 2009年5月31日(日) 15:25
by チルチル
う~ん、これは困りましたね・・
やはり関数の中だけで処理するのは無理なんでしょうか・・

Re:引数が配列の場合の処理

Posted: 2009年5月31日(日) 16:45
by box
今一度、当該の関数に何を渡して、当該の関数の中で何をしたいかを
整理してみたらいかがでしょうか。

単にint型1個だけを渡して処理したいのであれば、
わざわざ配列(へのポインタ)を渡す必要はないです。

Re:引数が配列の場合の処理

Posted: 2009年5月31日(日) 17:20
by チルチル
やりたい事をまとめると

①沢山ある引数の最後の引数に配列を渡す

②構造体の配列に代入

③配列だと後から数を変えやすそう?

④使わない時はできるだけ短くしたい
理想は隠し引数のように何も書かなくて良い

Re:引数が配列の場合の処理

Posted: 2009年5月31日(日) 18:03
by kazuoni
1~4のつながりがよく分かりません。。

1.は配列の先頭のポインタとサイズを渡せばこの質問の事は済みます。
 boxさんのおっしゃるとおり、1個の要素なら必要ないですが・・・

2.は構造体の配列に何を代入するのですか?
 1.で渡した配列は構造体の配列で、要素をごっそりすべてコピーするということですか?

3.は確かに、配列ならはa[100]→a[1000]とすれば要素数は変えられます。
 引数にするならば、aをint型の配列とすると、引数に(a,sizeof(a)/sizeof(a[0]))を加えれば、
 要素数を変えても、うまいこと配列にアクセスできます。

4.「何を」使わない時は「何を」できるだけ短くしたいのですか?
 隠し引数=可変個引数ということですか?それとも、省略実引数ですか?

Re:引数が配列の場合の処理

Posted: 2009年5月31日(日) 19:08
by チルチル
すいません①~④は特に繋がってるわけではありません・・

①は引数の最後を配列にして複数の数値を渡せるように
あと、ならべく少ない手順で渡したい・・

②は弾の構造体にも同じ要素数の配列があり、引数の配列の数値を構造体の配列に代入

③は後で要素数が足らなくなった場合に増やしやすいように・・

④弾の構造体の配列は角度とかを記録しておかないと表現できない弾幕を作る時に使うので普段は使いません
なので使わない時まで引数を渡すと見にくくなるので省略したい・・
隠し引数には詳しくないのでよくわかりませんが
描画系関数の反転フラグみたいな感じでしょうか・・

Re:引数が配列の場合の処理

Posted: 2009年5月31日(日) 20:43
by lbfuvab
デフォルト引数なんかで調べてみてはいかがでしょうか。

Re:引数が配列の場合の処理

Posted: 2009年6月01日(月) 19:50
by チルチル
あ~なるほど、こんな機能あったんですね
初期値の設定はできそうなんだけどな~
と思ってましたがプロトタイプ宣言時にするとは思いませんでした
まあ関数の方が上なら必要ないようですが

って事は
void DATA(a,b,c,data[5]=0);
みたいな感じですね
あとは()内で引数を渡す方法ですね

Re:引数が配列の場合の処理

Posted: 2009年6月03日(水) 00:40
by チルチル
>>data((int[2]){ 1, 2 });

これはできませんでしたが
こんな感じの方法は他にないでしょうか?

Re:引数が配列の場合の処理

Posted: 2009年6月03日(水) 01:37
by Justy

>こんな感じの方法は他にないでしょうか

 boostが使えるなら

[color=#d0d0ff" face="monospace]
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
#include <vector>

// 対象の配列
int arr[5];

// セット関数
void set_vector_data(const std::vector<int> &v)
{
const std::size_t arr_size = sizeof(arr)/sizeof(arr[0]);
const std::size_t v_size = v.size();
const std::size_t copy_size = arr_size < v_size? arr_size: v_size;
for(std::size_t n=0; n<copy_size; ++n)
arr[n] = v[n];
}

{ // 使うとき・・・お好みで (数字)(数字)...と繋げる
using namespace boost::assign;
set_vector_data(list_of(1));
set_vector_data(list_of(1)(2));
set_vector_data(list_of(1)(2)(3));
set_vector_data(list_of(1)(2)(3)(4));
}
[/color]


 使えないなら、オーバーロードしてみるのも一興。
[color=#d0d0ff" face="monospace]
// セット関数
void set_data_(int n, int val0, int val1 = 0, int val2 = 0, int val3 = 0)
{
if(n >= 1) arr[0] = val0;
if(n >= 2) arr[1] = val1;
if(n >= 3) arr[2] = val2;
if(n >= 4) arr[3] = val3;
}

void set_data(int val0, int val1, int val2, int val3)
{
set_data_(4, val0, val1, val2, val3);
}
void set_data(int val0, int val1, int val2)
{
set_data_(3, val0, val1, val2);
}
void set_data(int val0, int val1)
{
set_data_(2, val0, val1);
}
void set_data(int val)
{
set_data_(1, val);
}

{ // 使うとき
set_data(1);
set_data(1, 2);
set_data(1, 2, 3);
}
[/color]

Re:引数が配列の場合の処理

Posted: 2009年6月03日(水) 16:15
by チルチル
何だかすごそうな処理ですね・・
とりあえずboostとかオーバーロードとかを知らないので無理ですね・・
見た感じ値を代入する処理を先に作っているようですが
これだと一行に収まらないのでちょっとまずいですね・・

Re:引数が配列の場合の処理

Posted: 2009年6月03日(水) 22:06
by チルチル
原点に戻りますが

dat[0]=0,dat[1]=1,dat[2]=2,dat[3]=3,dat[4]=4;

DATA(a,b,c,data);

が一番短そうなんですが
dat配列の宣言と初期化を()の中でできないでしょうか?

Re:引数が配列の場合の処理

Posted: 2009年6月04日(木) 20:46
by たいちう
不自然な方法で短くことに何のメリットも感じませんが、
どうしてもというなら可変長引数について調べてみてはどうでしょうか。

http://www.kumei.ne.jp/c_lang/intro/no_43.htm

C++でクラスの設計の勉強をするのが一番のお勧めです。

Re:引数が配列の場合の処理

Posted: 2009年6月05日(金) 10:56
by たかぎ
> 不自然な方法で短く(書く)ことに何のメリットも感じませんが、

賛成です。
どうしてもやりたければ、最善の方法はC99に対応したコンパイラに変えることであり、次善策は、
int a[2]={1,2}; data(a);
と1行で書くことです。

Re:引数が配列の場合の処理

Posted: 2009年6月05日(金) 16:38
by チルチル
C99が何かよくわかりませんが
コンパイラの変更は無理ですね・・

可変長引数は「,」の数が増えるのでダメですね・・

よく考えたら
data((int[2]){ 1, 2 });
だって「,」が増えるから意味無いか・・

ここは配列の要素の数だけ隠し引数を用意しておくのがベストかな・・
要素を全部使わない時まで書かなきゃいけなくなる可能性だってあるし・・
増やすの簡単そうだし・・