配列引数のサイズを調べる
-
チルチル
配列引数のサイズを調べる
void main(){
int a[20];
int i;
for ( i = 0 ; i < sizeof(a) / sizeof(int) ; i ++ )
a = i;
}
上のように書くと配列の要素数だけループしますよね
しかし関数の引数に配列を渡した場合は先頭のアドレスが渡されるだけなので
sizeof演算子は要素数を返してくれません
何か良い方法は無いでしょうか?
int a[20];
int i;
for ( i = 0 ; i < sizeof(a) / sizeof(int) ; i ++ )
a = i;
}
上のように書くと配列の要素数だけループしますよね
しかし関数の引数に配列を渡した場合は先頭のアドレスが渡されるだけなので
sizeof演算子は要素数を返してくれません
何か良い方法は無いでしょうか?
-
zwi
Re:配列引数のサイズを調べる
こんな感じですかね。
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;
}
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;
}
-
zwi
Re:配列引数のサイズを調べる
C言語の引数の受け渡しの仕組みでは無理です。
オブジェクト指向言語のJavaやC#なら言語仕様自体で配列の仕組みが違うので必要ないですが。
C++でもクラスを使えば擬似的には可能です。
オブジェクト指向言語のJavaやC#なら言語仕様自体で配列の仕組みが違うので必要ないですが。
C++でもクラスを使えば擬似的には可能です。
-
zwi
Re:配列引数のサイズを調べる
STLのvectorを参照渡しで使います。
すいません、いま説明している時間が無いので検索してみてください。
分からなければ、明日またお答えします。
すいません、いま説明している時間が無いので検索してみてください。
分からなければ、明日またお答えします。
-
array
Re:配列引数のサイズを調べる
配列の要素数は一般的に以下の形式が多用されてるみたいです。
これでプログラムがすっきりすると思います。
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:配列引数のサイズを調べる
本文読み直したら、勘違いしていました^^;
関数に配列を渡しても、要素数は引き継げないっていう話でしたね・・・・申し訳ないです。
関数先にC++のテンプレートを用いれば、要素数も引き継いでくれるのですが、一応解決された
みたいなのでまたの機会に。
関数に配列を渡しても、要素数は引き継げないっていう話でしたね・・・・申し訳ないです。
関数先にC++のテンプレートを用いれば、要素数も引き継いでくれるのですが、一応解決された
みたいなのでまたの機会に。
-
GPGA
Re:配列引数のサイズを調べる
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:配列引数のサイズを調べる
C++の次期規格であれば...
template <typename T, std::size_t N>
constexpr std::size_t count(T (&arg)[N])
{
return N;
}
とすれば、定数式として扱うこともできますね。-
Justy
Re:配列引数のサイズを調べる
>解説サイトとかあったら教えてください
少し古い記事ですが
テンプレート引数の一致
ttp://msdn.microsoft.com/ja-jp/library/cc440189(VS.71).aspx
-
チルチル
Re:配列引数のサイズを調べる
う~ん良くわかりませんでしたね・・
ちなみに
template<class T, int N>
のclassとintの違いは何でしょうか?
あとTに入る型が全て同じの場合に
Nだけにする事はできないでしょうか?
ちなみに
template<class T, int N>
のclassとintの違いは何でしょうか?
あとTに入る型が全て同じの場合に
Nだけにする事はできないでしょうか?
-
組木紙織
Re:配列引数のサイズを調べる
>あとTに入る型が全て同じの場合に
>Nだけにする事はできないでしょうか?
部分特殊化を使えばOK.
>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:配列引数のサイズを調べる
これは良いですね、最初に比べてかなり短くなりました
どこまで短くできるか気になりますね
そこで
>template<int N>
>(int (&Graph)[N])
ここをもっと短く書けないでしょうか?
あとテンプレートの柔軟性に期待して
関数を呼ぶ前に配列を作成しないで
引数の(と)の中に数値や変数を並べて渡せないでしょうか?
つまり
Draw({1,2,3,4,5});
見たいな事はできないでしょうか?
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:配列引数のサイズを調べる
>これは練習で作った関数ですが
>どこまで短くできるか気になりますね
意図が見えないのですが、
ループ回さずにreturn N;
で十分なような気が。。。
テンプレートのところは短くできないです。
>Draw({1,2,3,4,5});
>見たいな事はできないでしょうか?
次期C++ならできるような気もしますが、現在はマクロを併用して擬似的にするしかないのかな、
配列を引数にと考えなければ可長変引数を使えばできますけど、安全性に不安が出てきますね。
>どこまで短くできるか気になりますね
意図が見えないのですが、
ループ回さずにreturn N;
で十分なような気が。。。
テンプレートのところは短くできないです。
>Draw({1,2,3,4,5});
>見たいな事はできないでしょうか?
次期C++ならできるような気もしますが、現在はマクロを併用して擬似的にするしかないのかな、
配列を引数にと考えなければ可長変引数を使えばできますけど、安全性に不安が出てきますね。
-
チルチル
Re:配列引数のサイズを調べる
簡略化はこの辺が限界みたいですね
でも当初の目的は達せたので助かりました
これから実装してみるので少々お待ちください
ちなみに
>現在はマクロを併用して擬似的にするしかないのかな
これはどんな感じでしょうか?
でも当初の目的は達せたので助かりました
これから実装してみるので少々お待ちください
ちなみに
>現在はマクロを併用して擬似的にするしかないのかな
これはどんな感じでしょうか?
-
たかぎ
Re:配列引数のサイズを調べる
こんな風にして定数式にすることもできます。
template <typename T, std::size_t N> char (*count_helper(T (&array)[N]))[N]; #define count(array) sizeof(*count_helper(array))マクロであること自体も問題点を除けば、結構優れものかもしれません。
-
たかぎ
Re:配列引数のサイズを調べる
> どんな感じで使うのでしょうか?
そんなに難しく考える必要はありません。
そんなに難しく考える必要はありません。
int a[7]; std::size_t n = count(a);とすれば、nに7が代入されるはずです。
-
たかぎ
Re:配列引数のサイズを調べる
> しかしこれでDraw({1,2,3,4,5});
> が擬似的に実現できるのでしょうか?
それを目指したものではありません。
Draw({1, 2, 3, 4, 5})を実現するには、C99かC++の次期標準でなければ無理です。GCCでも何とかなります。
多少シンタックスを変えてもよいなら実現することは可能ですが、オーバーヘッドが大きくなります。
> が擬似的に実現できるのでしょうか?
それを目指したものではありません。
Draw({1, 2, 3, 4, 5})を実現するには、C99かC++の次期標準でなければ無理です。GCCでも何とかなります。
多少シンタックスを変えてもよいなら実現することは可能ですが、オーバーヘッドが大きくなります。
-
たかぎ
Re:配列引数のサイズを調べる
> Draw({1,2,3,4,5});は無理だとしても
> 予め配列を作成しておかなくても良いような方法は無いでしょうか?
要素数の上限があらかじめ決まっているのであれば、make_tupleを使う方法もありますし、
可変個数引数を使う方法もありますが、あまりお勧めはしません。
> 予め配列を作成しておかなくても良いような方法は無いでしょうか?
要素数の上限があらかじめ決まっているのであれば、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:配列引数のサイズを調べる
遅くなってしまいましたが、
>> 部分特殊化を使えばOK.
>関数テンプレートの部分特殊化はできないので、これは単なる多重定義ですね。
正しくないことを書いてしまってすみませんでした。
>> 部分特殊化を使えばOK.
>関数テンプレートの部分特殊化はできないので、これは単なる多重定義ですね。
正しくないことを書いてしまってすみませんでした。