• ベストアンサー

関数へのポインタ渡しでの配列の初期化について

はじめまして、C言語の基本的な質問をさせてください。 C言語で、外部関数へポインタで引数を渡す場合に、 関数に渡されるのはアドレスですよね? で、渡された関数側でそのポインタの配列の初期化を するときにはアドレスだけの情報だと、要素数がいくつ あるか分からず、領域の破壊をしてしまいそうな気が するのですが?いかがでしょうか? また、関数かなんかで、配列の要素数が分かる関数が あったような気がするのですが、それもアドレスだけ でわかるのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.1

疑問に思っていらっしゃる通りです。 渡された関数側では、要素数がいくつあるかわかりません。 初期化をするならば、ポインタと一緒に、要素数の情報も渡してやる必要があります。 配列の要素数がわかる関数はありません。 マクロ(プリプロセッサ)で、配列要素数を計算するのは可能ですが、 これは使用場所が限定されています。 配列を宣言したすぐ近くでないと役に立ちません。 渡された関数側では使えません。 C言語では、配列はその要素数とともに扱う必要があり、 そこをうっかりするとバグが発生する危険があります。

H-hirosawa
質問者

お礼

早速の回答ありがとうございます。 やはりそうですよね? ヘッダでインクルードしてある構造体の配列などなら 初期化することは可能だと思いますが、通常の配列だと 引数として要素数をわたしてやる必要がありますね。 ありがとうございました。

関連するQ&A

  • 関数へのポインタ渡し

    下位関数へポインタのアドレスを渡して(器を渡して) 内容を設定してもらうというのは、よくやることと おもいます。 そのポインタの領域は、普通は上位関数で実体を確保する と思っていたのですが、下位関数での実体確保することは 可能なのでしょうか? 対象はc言語です。 宜しく御願い致します。

  • 多次元配列のポインタ渡し

    C++を使用しています。 多次元配列を関数の引数として渡したいとき、関数側では void A::Func(int a[10][20][30])~ 呼びだし側では Finc(a); とやればいいのはわかります。 お聞きしたいのは、仮引数として呼び出された配列(上でいうa)をクラスのメンバ変数として保持したい場合の方法です。 aは先頭アドレスなのでそこを差すポインタを受ければいい、っていうことはわかりますが、 この方法ですと、受けたメンバ変数が配列みたいに[]を使ってアクセスできません。 (メンバ変数のポインタは配列じゃないから当然ですよね) これを通常の配列みたいに扱えるようにするにはどうしたらいいでしょうか。

  • ポインタによる関数への配列渡し

    林晴比古さんの「新C言語入門」でC言語を勉強している初心者です。 現在ポインタの勉強をしています。色々教科書の文例等をポインタで書くとどうなるか試しております。 上書P200練習問題2に「配列の最大値を返す(その際配列の長さを渡す)」プログラムがあり、それをポインタで渡すプログラムに直してみました。 仮引数に「maxdata」を設定し、そのアドレスを関数側に渡し、関数側ではポインタとして受け取る(そうすれば関数側からはreturnで値を返す必要がない)、と考え、下記のように書いてみました。 #include <stdio.h> void max_of_array(int n[], int len, int *ans); int main(void) { int dt[6] = {50,20,80,30,10,40}; int maxdata; max_of_array(dt,6,&maxdata); printf("最大値=%d\n", maxdata); return 0; } void max_of_array(int n[], int len, int *ans) { int i; ans = &n[0]; for (i=1; i<len; i++){ if (*ans < n[i]) *ans = n[i]; } } しかしコンパイルすると、何故か「最大値=1」となってしまいます。(正しくは80です) 他にも色々試してみましたがうまくいかず、かなり考えてみたのですがどうしても分かりません。お分かりの方、どうすれば正しくなるのが教えてください、よろしくお願いします。

  • 配列ポインタの関数中のメモリ領域

    C初心者です。 関数中で配列ポインタを宣言する場合についての質問です。 たとえばDouble型の2次元のローカルな配列ポインタを用いる場合、 その配列要素数が100である場合は void 関数名(引数1,引数2,...){ int i; double *a[2]; for(i=0;i<2;i++){ a[i] = (double*)malloc(100*sizeof(double)); } for(i=0;i<2;i++){ free(a[i]); } } またこの値を引数1とする場合、引数1をoutとすると void 関数名(double *out,....) とし、 for(i=0;i<2;i++){ out[i] = a[i]; } とすればよいのでしょうか? もしこれがあっているとすると、つぎのような現象で困っています。 配列要素数を50000個ぐらいとし、複数の関数で、同様に mallocを用いて、配列ポインタのローカルでメモリ領域を確保しようとした場合、コンパイルは成功するのですが、その後実行すると、エラーが発生したというメッセージとともにコマンドウィンドが強制終了します。 コンパイラはVisual C++ EXpress Edition 2008です。 データサイズを小さくすると、エラーは起きません。 malloc関数で確保するメモリサイズは、関数の入力引数で定義された変数を用いて計算しており、データサイズに応じて変更されます。 よろしくお願いいたします。

  • 続ポインタによる関数への配列渡し

    連続での質問すみません。 林晴比古さんの「新C言語入門」で勉強している初心者です。 ポインタを勉強中で、色々な例文をポインタで書けるかどうか 試しております。 上書P199に「安全な数値入力を行うプログラム」が出ています。 これは入力時問題点を抱えるscanfに入力させるのでなくchar型に入力させ、 それをint型に変換して出力するという内容で、案内メッセージも関数内で表示することになっています。 以下そのプログラムを引用します。 #include <stdio.h> #include <stdlib.h> int getint(char msg[]); int main(void) { int n; n = getint("数値を入力してください:"); printf("入力した数値=%d\n",n); return 0; } int getint(char msg[]) { char ss[80]; printf("%s",msg); gets(ss); return atoi(ss); } (以上林晴比古氏「新C言語入門」P199より引用) これをポインタによって書き換えようとしているのですがうまくいきません。 「本引数として主文でint型のnを設定し、それを関数側のchar型のssをポインタにして 仮引数として受け取れば、最後にreturnで返さなくても、参照できるのでないか」 と思い色々試してみましたがうまくいきません。 どうもコンパイルのエラーを確認すると型が違うので駄目なようです。 なるほどそれはそうでした… それ以外の方法も色々試してみましたが、結局うまくいきませんでした。 どのようにすればポインタでは上の文章を表現できるのでしょうか。 (あるいは表現出来ないのでしょうか) お分かりの方、よろしくお願いします。

  • android-JNIでクラス配列参照方法について

    androidのJNIで関数引数をクラス配列にした場合、C側ではこのポインタをどのようにすれば取得出来るのでしょうか? 一応GetByteArrayElements()を使用してクラス配列の要素数までは取得できましたが、このクラスのポインタの取得方法が出来ません。 ※クラス配列にある変数をC言語側で参照したいと考えております。 (このクラスはC言語の構造体として扱うようにしています)

  • 構造体配列のポインタを引数に

    こんばんは。 Visual C++ 2008 Express Edition を使っています。 C++のあるプログラム内の関数で、構造体の1次元配列のポインタを引数に取ろうと思っているのですが上手くいきません。 関数の目的としては、関数側と呼び出す側のファイルを分けているので、関数側のグローバルな構造体配列のアドレスに呼び出し側の構造体配列のアドレスを代入することです。 構造体はExampleと型を定義してあります。 ・関数側 Example *global_ex[10]; void GetEx(Example *ex[])  // ←2つ目のエラー {   global_ex = ex;  // ←1つ目のエラー } ・呼び出し側(呼び出し側の関数内)   Example ex[10];   (exの初期化)   GetEx(&ex); ・エラー  error C2440: '=' : 'Example *[]' から 'Example [15]' に変換できません。配列型への変換はありませんが、参照またはポインタから配列への変換があります。  error C2664: 'GetEx' : 1 番目の引数を 'Example (*)[15]' から 'Example *[]' に変換できません。 プログラムとエラーは以上です。 何をすれば解決できるのか、ご存じの方いらっしゃいましたらよろしくおねがいします。 CとC++は独学で学んでいるので偏りがあると思います。 「基本的な○○が分かっていないのでは?」と感じたらその点もご指摘頂けると嬉しいです。。

  • 配列の参照渡し

    以下のC言語のプログラムを教えてください。 お願いします。 (1)標準入力から文字列(2 文字以上)を入力し,文字数を計上すると共に,入力された文 字列の逆順に入れ替える処理を実現せよ.なお,以下の要件を満たしたプログラムを作 成すること. ・ 入力された文字列は,char 型の配列(要素数50)で受け取ること ・ 文字数を計上するcount 関数(引数:配列のアドレス,戻り値:文字数)を定義 し,main 関数より呼び出すこと ・ 文字列を逆順に入れ替えるreverse 関数(引数:配列のアドレス,戻り値:無し) を定義し,main 関数より呼び出すこと ・ 標準出力の処理は,main 関数で記述すること 【プロトタイプ宣言】 int count(char *str); void reverse(char *str); 【実行結果】 文字列を入力してください(2 文字以上) apple 文字数 = 5 入れ換え前 apple 入れ換え後 elppa $ ---------------------------------------------------------------------------- (2)char 型の配列(要素数50)を2 つ宣言し,標準入力から2 つの文字列を入力せよ. そして,格納した字列を入れ替える関数(swapstr 関数)を作成し,入れ替え前と入れ替 え後の配列内の値(文字列)を配列名とともに標準出力するプログラムを作成せよ. 【プロトタイプ宣言】 void swapstr(char *str1, char *str2); 【実行結果】 2 つの文字列を入力してください apple strawberry 入れ換え前 配列str1 = apple 配列str2 = strawberry 入れ換え後 配列str1 = strawberry 配列str2 = apple

  • 配列表現とポインタ表現

    配列とポインタの2通りの表現で表せる場面によく遭遇します。例えば、pというdouble型の配列に乱数を10個発生させて格納したい時など、 for(i=0;i<10;i++) *(p+i) = (double) rand(); for(i=0; i<10; i++) p[i] = (double) rand(); のように、配列とポインタの2通りの表現が考えられると思いますが、複雑な場合などは特に、見た感じは配列のほうが分かりやすいと思います。 まだ、C言語の初級から中級向けの本しか読んでいないのですが、標準関数の多くがポインタを引数や返り値としていることを知りました。わざわざポインタ表現にすることの意義は、実行速度が上がることと、標準関数の多くがポインタを引数や返り値としているからと理解して良いのでしょうか。

  • ポインタの配列について

    はじめまして。 基本的な質問で恐縮ですが、質問があります。 例えば、char *name[] = {"Alice","Ben","Chris","Diana","Elmo"} のようなポインタの配列を宣言・初期化したとき、配列nameの各要素の 中身には、初期化子として与えた、文字列の先頭アドレスが 格納されているという解釈でよろしいのでしょうか?つまり、 *(name+1)やname[1]は、「文字列Benの先頭アドレスを指す」という意 味でよろしいのでしょうか?また、このとき、(name+1)というように *をつけないときは、「文字列Benの先頭アドレスを格納したメモリの 先頭アドレス」というような解釈でよろしいのでしょうか? どうかご教授お願いします。

専門家に質問してみよう