質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.44%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

811閲覧

c言語で配列の要素数を求める関数を作りたい

mamukura

総合スコア4

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2023/03/09 04:38

実現したいこと

・配列のポインタを受け取り、その配列の要素数を返す関数が作りたい。
・配列やポインタの仕様に関して理解できていない部分を明確にしたい。

前提

c言語

発生している問題・エラーメッセージ

おそらく配列のポインタから配列全体のサイズを求められていない。 エラーメッセージ ```関節参照のレベルが異なっています。 ### 該当のソースコード ```c言語 ソースコード ```#include <stdio.h> size_t count(char *v) { size_t n; n = sizeof(v) / sizeof(&v[0]); return n; } int main(void) { char a[][5] = { "LISP","C","Ada","fin"}; char* p[] = { "PAUL","X","MAC","fin"}; printf("count(a)=%zu\n", count(a)); printf("count(v)=%zu\n", count(p)); for (int i = 0; i < count(a); i++) printf("a[%d]=%s\n", i, a[i]); for (int i = 0; i <count(p); i++) printf("p[%d]=%s\n", i, p[i]); return 0; } ### 試したこと sizeofを使わずにwhile(v[n++])などで要素数を求めようとした。 count内の式の分母をsizeof(v[n])にしたが、エラーが起こってしまった。 ### 補足情報(FW/ツールのバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

コンパイルできないのは、char a[][5] を受け取るなら引数の型は char (*)[5] で、char* p[] を受け取るなら引数の型は char** だからです。

・配列のポインタを受け取り、その配列の要素数を返す関数が作りたい。

C言語ではできません。配列のポインタだけを渡すとサイズが渡らないですし、異なる型の配列を受け取る関数が作れません。

マクロなら可能です。

c

1#define COUNT(v) (sizeof(v) / sizeof(v[0]))

投稿2023/03/09 05:59

int32_t

総合スコア21207

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mamukura

2023/03/09 06:16

回答ありがとうございます。 ポインタのポインタ?というのも作れるのですね。 まだ私の知識が浅くイメージしづらくはありますが頑張ってみます。 別の解決策も書いていただきありがとうございます。 参考にさせていただきます。
mamukura

2023/03/09 06:30

みなさん回答ありがとうございました。 マクロという解決方法も載せてくださったこちらの回答をベストアンサーとさせていただきました。 みなさんのおかげで何が分かっていないのか見えてきましたのでこれからも勉強していきます。
guest

0

通常、配列を処理する関数には、配列とその要素数をパラメータとして渡します。

C

1#include <stdio.h> 2 3void arr_print(int no_arr,char arr[][5]){ 4 int i; 5 printf("arr_print no_arr=%d\n",no_arr); 6 for (i = 0 ;i < no_arr;i++){ 7 printf("arr[%d]=%s\n",i,arr[i]); 8 } 9} 10void arr_print2(int no_arr,char *arr[]){ 11 int i; 12 printf("arr_print2 no_arr=%d\n",no_arr); 13 for (i = 0 ;i < no_arr;i++){ 14 printf("arr[%d]=%s\n",i,arr[i]); 15 } 16} 17int main(void) { 18 19 char a[][5] = { "LISP","C","Ada","fin"}; 20 char* p[] = { "PAUL","X","MAC","fin"}; 21 22 int no_a = sizeof(a)/sizeof(char[5]); 23 int no_p = sizeof(p)/sizeof(char*); 24 25 26 printf("%d %d\n",no_a,no_p); 27 28 for (int i = 0; i < no_a; i++) 29 printf("a[%d]=%s\n", i, a[i]); 30 31 for (int i = 0; i < no_p; i++) 32 printf("p[%d]=%s\n", i, p[i]); 33 34 arr_print(no_a,a); 35 arr_print2(no_p,p); 36 return 0; 37} 38

実行結果
4 4
a[0]=LISP
a[1]=C
a[2]=Ada
a[3]=fin
p[0]=PAUL
p[1]=X
p[2]=MAC
p[3]=fin
arr_print no_arr=4
arr[0]=LISP
arr[1]=C
arr[2]=Ada
arr[3]=fin
arr_print2 no_arr=4
arr[0]=PAUL
arr[1]=X
arr[2]=MAC
arr[3]=fin

投稿2023/03/09 06:18

tatsu99

総合スコア5487

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mamukura

2023/03/09 06:26

回答ありがとうございます。 やはり、要素数を求めるにはmain関数内でsizeofを使うのですね。 丁寧にコードまで書いていただきありがとうございます。 参考にさせていただきます。
guest

0

n = sizeof(v) / sizeof(&v[0]);

v ってのはポインタなので、sizeof(v)は、当然、ポインタのサイズになります
イマドキの64ビットマシンであるなら、8固定です

sizeof(&v[0]);

v[0] ってのは、char型変数となりますが、&をつけてchar型のアドレスを指してますんで、そのサイズ、8が求められます

ってことで、

・配列のポインタを受け取り、その配列の要素数を返す関数が作りたい。

これはできません。

投稿2023/03/09 05:21

y_waiwai

総合スコア87849

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mamukura

2023/03/09 05:32

回答ありがとうございます。 char*p[]の要素の全ポインタのサイズを関数に与えることはできないためつくれないし、&v[0]はそもそもポインタではなくアドレスのサイズだから別物ということですかね? もう少し調べて頑張ってみます。
y_waiwai

2023/03/09 05:51

配列が見えているところであるなら、配列全体のサイズが取れるためサイズの算出は可能ですが、 ポインタから求めるってのはムリムリですね main関数中であるなら、sizeof(p)/sizeof(*p) で、3が取れます
mamukura

2023/03/09 06:18

返信ありがとうございます。 main関数内であれば配列の情報からsizeof(p)が出せるのですね。 自分が何が分かっていなかったのかが見えてきました。 ありがとうございます。
guest

0

配列のポインタを受け取り、その配列の要素数を返す関数が作りたい。

残念ながらポインタが持っているのは配列先頭のアドレスだけであり、配列の大きさ情報を持っていません。

投稿2023/03/09 05:02

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mamukura

2023/03/09 05:27

回答ありがとうございます。 配列の先頭要素がアドレスが関数に渡されるだけで配列の情報は何も持っていないのですね。 理解できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.44%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問