配列引数のサイズを調べる

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

配列引数のサイズを調べる

#1

投稿記事 by チルチル » 16年前

void main(){
int a[20];
int i;

for ( i = 0 ; i < sizeof(a) / sizeof(int) ; i ++ )
a = i;
}

上のように書くと配列の要素数だけループしますよね
しかし関数の引数に配列を渡した場合は先頭のアドレスが渡されるだけなので
sizeof演算子は要素数を返してくれません
何か良い方法は無いでしょうか?

box

Re:配列引数のサイズを調べる

#2

投稿記事 by box » 16年前

要素数も引数に加えてあげてください。

zwi

Re:配列引数のサイズを調べる

#3

投稿記事 by zwi » 16年前

こんな感じですかね。
void func(int a[/url],int size)
{
int i;
for ( i = 0 ; i < size ; i ++ )
a = i;
}
}
int main(){
int a[20];
func(a,sizeof(a) / sizeof(int));
return 0;
}

ちなみに、呼び出しをこうする方法もあります。
#define FUNC(array) func((array),sizeof((array))/sizeof(int))
int main(){
int a[20];
FUNC(a);
return 0;
}

チルチル

Re:配列引数のサイズを調べる

#4

投稿記事 by チルチル » 16年前

あ~すいません説明不足でした
要素数を別に渡さなくてもできる方法は無いでしょうか?

zwi

Re:配列引数のサイズを調べる

#5

投稿記事 by zwi » 16年前

C言語の引数の受け渡しの仕組みでは無理です。
オブジェクト指向言語のJavaやC#なら言語仕様自体で配列の仕組みが違うので必要ないですが。
C++でもクラスを使えば擬似的には可能です。

チルチル

Re:配列引数のサイズを調べる

#6

投稿記事 by チルチル » 16年前

う~ん無理ですか・・
ちなみに擬似的にとはどんな感じでしょうか?

zwi

Re:配列引数のサイズを調べる

#7

投稿記事 by zwi » 16年前

STLのvectorを参照渡しで使います。
すいません、いま説明している時間が無いので検索してみてください。
分からなければ、明日またお答えします。

チルチル

Re:配列引数のサイズを調べる

#8

投稿記事 by チルチル » 16年前

あ~残念ですが今回のコードはSTLとの相性が最悪なので無理そうですね・・
どうもありがとうございました

array

Re:配列引数のサイズを調べる

#9

投稿記事 by array » 16年前

配列の要素数は一般的に以下の形式が多用されてるみたいです。
int main() {
    int array[20]; 

    // num は20になる
    int num = sizeof( array ) / sizeof( array[0] );

    return 0;
}
また、define定義を用いれば

#define array_sizeof(p) ( sizeof( p) / sizeof( (p)[0] ) )

int main() {
    int array[20]; 

    // num は20になる
    int num = array_sizeof(array);

    return 0;
}

これでプログラムがすっきりすると思います。

array

Re:配列引数のサイズを調べる

#10

投稿記事 by array » 16年前

本文読み直したら、勘違いしていました^^;

関数に配列を渡しても、要素数は引き継げないっていう話でしたね・・・・申し訳ないです。

関数先にC++のテンプレートを用いれば、要素数も引き継いでくれるのですが、一応解決された
みたいなのでまたの機会に。

チルチル

Re:配列引数のサイズを調べる

#11

投稿記事 by チルチル » 16年前

これは結構画期的ですね
まあ呼ぶ時には確定しているので定数で行ってみます

GPGA

Re:配列引数のサイズを調べる

#12

投稿記事 by GPGA » 16年前

C++でtemplateを使用すれば、引数をサイズを渡す必要はありません。
#include <iostream>

template<class T, int N>
void func(T (&ar)[N]) {
	for (int i = 0; i < N; ++i) {
		std::cout << ar << std::endl;
	}
}

int main() {
	int data[/url] = { 0, 1, 2, 3 };
	func(data);
}

たかぎ

Re:配列引数のサイズを調べる

#13

投稿記事 by たかぎ » 16年前

C++の次期規格であれば...
template <typename T, std::size_t N>
constexpr std::size_t count(T (&arg)[N])
{
    return N;
}
とすれば、定数式として扱うこともできますね。

チルチル

Re:配列引数のサイズを調べる

#14

投稿記事 by チルチル » 16年前

これも使えそうですね
どういう仕組みになっているのでしょうか?
解説サイトとかあったら教えてください

Justy

Re:配列引数のサイズを調べる

#15

投稿記事 by Justy » 16年前


>解説サイトとかあったら教えてください

 少し古い記事ですが

テンプレート引数の一致
ttp://msdn.microsoft.com/ja-jp/library/cc440189(VS.71).aspx

チルチル

Re:配列引数のサイズを調べる

#16

投稿記事 by チルチル » 16年前

う~ん良くわかりませんでしたね・・

ちなみに
template<class T, int N>
のclassとintの違いは何でしょうか?

あとTに入る型が全て同じの場合に
Nだけにする事はできないでしょうか?

組木紙織

Re:配列引数のサイズを調べる

#17

投稿記事 by 組木紙織 » 16年前

>あとTに入る型が全て同じの場合に
>Nだけにする事はできないでしょうか?

部分特殊化を使えばOK.
#include <iostream>
using namespace std;

//int 型バージョン
template<std::size_t N>
void func(int (&ar)[N])
{
	std::cout << "int " << std::endl;
	for(int i=0; i<N;++i){
		std::cout << ar  << std::endl;
	}
}

//なんでも型バージョン
template<class T, std::size_t N>
void func(T (&ar)[N]) {
	std::cout << "not int" << std::endl;
	for (int i = 0; i < N; ++i) {
		std::cout << ar << std::endl;
	}
}

int main() {
	//int型の配列
	int data[/url] = { 0, 1, 2, 3 };
	//const int型の配列
	const int data2[/url]={0, 1, 2, 3};
	func(data);
	func(data2);
	return 0;
}

チルチル

Re:配列引数のサイズを調べる

#18

投稿記事 by チルチル » 16年前

これは良いですね、最初に比べてかなり短くなりました
template<int N>
int Draw(int (&Graph)[N]){
	int i;
	for( i=0;i<N;i++ );
	return i;
}
これは練習で作った関数ですが
どこまで短くできるか気になりますね

そこで
>template<int N>
>(int (&Graph)[N])
ここをもっと短く書けないでしょうか?

あとテンプレートの柔軟性に期待して
関数を呼ぶ前に配列を作成しないで
引数の(と)の中に数値や変数を並べて渡せないでしょうか?

つまり
Draw({1,2,3,4,5});
見たいな事はできないでしょうか?

組木紙織

Re:配列引数のサイズを調べる

#19

投稿記事 by 組木紙織 » 16年前

>これは練習で作った関数ですが
>どこまで短くできるか気になりますね
意図が見えないのですが、
ループ回さずにreturn N;
で十分なような気が。。。
テンプレートのところは短くできないです。


>Draw({1,2,3,4,5});
>見たいな事はできないでしょうか?

次期C++ならできるような気もしますが、現在はマクロを併用して擬似的にするしかないのかな、
配列を引数にと考えなければ可長変引数を使えばできますけど、安全性に不安が出てきますね。

たかぎ

Re:配列引数のサイズを調べる

#20

投稿記事 by たかぎ » 16年前

> 部分特殊化を使えばOK.

関数テンプレートの部分特殊化はできないので、これは単なる多重定義ですね。

チルチル

Re:配列引数のサイズを調べる

#21

投稿記事 by チルチル » 16年前

簡略化はこの辺が限界みたいですね
でも当初の目的は達せたので助かりました

これから実装してみるので少々お待ちください

ちなみに
>現在はマクロを併用して擬似的にするしかないのかな
これはどんな感じでしょうか?

たかぎ

Re:配列引数のサイズを調べる

#22

投稿記事 by たかぎ » 16年前

こんな風にして定数式にすることもできます。
template <typename T, std::size_t N>
char (*count_helper(T (&array)[N]))[N];

#define count(array)  sizeof(*count_helper(array))
マクロであること自体も問題点を除けば、結構優れものかもしれません。

チルチル

Re:配列引数のサイズを調べる

#23

投稿記事 by チルチル » 16年前

う~ん良くわからないですね・・
どんな感じで使うのでしょうか?

たかぎ

Re:配列引数のサイズを調べる

#24

投稿記事 by たかぎ » 16年前

> どんな感じで使うのでしょうか?

そんなに難しく考える必要はありません。
int a[7];
std::size_t n = count(a);
とすれば、nに7が代入されるはずです。

チルチル

Re:配列引数のサイズを調べる

#25

投稿記事 by チルチル » 16年前

なるほど、確かにそうなる気がしますね
しかしこれでDraw({1,2,3,4,5});
が擬似的に実現できるのでしょうか?

たかぎ

Re:配列引数のサイズを調べる

#26

投稿記事 by たかぎ » 16年前

> しかしこれでDraw({1,2,3,4,5});
> が擬似的に実現できるのでしょうか?

それを目指したものではありません。

Draw({1, 2, 3, 4, 5})を実現するには、C99かC++の次期標準でなければ無理です。GCCでも何とかなります。
多少シンタックスを変えてもよいなら実現することは可能ですが、オーバーヘッドが大きくなります。

チルチル

Re:配列引数のサイズを調べる

#27

投稿記事 by チルチル » 16年前

これは無理ですか・・

Draw({1,2,3,4,5});は無理だとしても
予め配列を作成しておかなくても良いような方法は無いでしょうか?

たかぎ

Re:配列引数のサイズを調べる

#28

投稿記事 by たかぎ » 16年前

> Draw({1,2,3,4,5});は無理だとしても
> 予め配列を作成しておかなくても良いような方法は無いでしょうか?

要素数の上限があらかじめ決まっているのであれば、make_tupleを使う方法もありますし、
template <typename T> void Draw(const T& e1);
template <typename T> void Draw(const T& e1, const T& e2);
template <typename T> void Draw(const T& e1, const T& e2, const T& e3);
...
のように、数だけ多重定義しておく方法もあります。

可変個数引数を使う方法もありますが、あまりお勧めはしません。

チルチル

Re:配列引数のサイズを調べる

#29

投稿記事 by チルチル » 16年前

う~んこういうのは無理がありそうですね・・

実装しているうちに何か変わるかもしれませんから色々やってみます

チルチル

Re:配列引数のサイズを調べる

#30

投稿記事 by チルチル » 16年前

うまく行きました
どうもありがとうございます

組木紙織

Re:配列引数のサイズを調べる

#31

投稿記事 by 組木紙織 » 16年前

遅くなってしまいましたが、

>> 部分特殊化を使えばOK.

>関数テンプレートの部分特殊化はできないので、これは単なる多重定義ですね。

正しくないことを書いてしまってすみませんでした。

閉鎖

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