• ベストアンサー

ポインタ配列の値引き渡しについて

関数を作る際 func(int p[][]) →コンパイルエラー func(int *p[]) →コンパイルOK になるのは何故ですか? 同じことを言っているように思うのですが?

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

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「ポインタは特に指示しなくても、大きさが確定する」でだいたい当たり. まず, C において配列には「1次元配列」しか存在しません. で, 配列の要素には非常に大雑把にいうと「宣言の時点で大きさが確定しなければならない」という条件が付きます (正確な条件はめんどくさいので省略). ということで ・int p[][]: p の要素は「int []」であるが, この [] の中に大きさが書かれていない→要素の大きさが確定しないのでアウト ・int *p[]: p の要素は「int *」で, 大きさが確定しているのでセーフ ・int p[][4]: p の要素は「int [4]」. これは大きさが確定するのでセーフ ついでに余談: 関数の仮引数に配列を書くと自動的にポインタと解釈される.

NEW2010
質問者

お礼

分かりやすいご説明ありがとうございます。 物凄くよくわかりました。 今後ともよろしくお願いします。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

残念ながらこの 2つは「同じことを言っている」わけではないので.... func(int p[][]) と同じことになるのは func(int (*p)[]) だったりする (そしてもちろん同様にエラーになる).

NEW2010
質問者

お礼

func(int p[][4]) →コンパイルOK func(int *p[]) →コンパイルOK この違いはなんでしょうか? *p[]=p[][4]でもなさそうですし?ポインタは特に指示しなくても、大きさが確定するからでしょうか?

NEW2010
質問者

補足

すいません、お礼を言うのを忘れていました。 早速のご返信ありがとうございます。 なにとぞ、↓の質問も答えていただきますよう、お願い申し上げます。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • C言語の基本的な質問ですが、関数へのポインタの宣言

    関数へのポインタの質問です。 下のように、関数へのポインタを使ったプログラムを書きました。 (関数へのポインタを理解するためのものなので、実用的な意味はありません。(*^_^*) また、このプログラムはコンパイルもリンクも実行も問題なく出来ます。) #include <stdio.h> int add_func(int,int); (*func_p0) (int,int); int main(void) { int (*func_p1) (int,int); int (*func_p2) ( ); int hoge0,hoge1,hoge2; func_p0=add_func; hoge0=func_p0(3,5); printf("0 : 3+5は%d\n",hoge0); func_p1=add_func; hoge1=func_p1(3,5); printf("1 : 3+5は%d\n",hoge1); func_p2=add_func; hoge2=func_p2(3,5); printf("2 : 3+5は%d\n",hoge2); return(0); } int add_func(int x, int y) { return(x+y); } func_p0のように戻り値の型を書かない場合と、func_p1やfunc_p2のように戻り値の型を書くのとでは何が違うのでしょうか。 func_p0は外部変数ですが、自動変数にする(main関数の中で同様に宣言。)とコンパイルエラーになります。 それはなぜですか。 func_p1のように引数の型が書いてあるのと、func_p2のように引数の型が書いていないのでは何が違うのでしょうか。 int (*func_p2) ( );というのは、int (*func_p2) (void);とは違うんですよね?

  • 教えてポインタ

    例えば、以下のようなソース。 関数の中で、引数のポインタに値を入れてmainに戻す。 とても簡単なものです。 void func(int *N) {  *N=0; } main {  int  *N=1;  func(N);  printf("%d",*N) } 疑問は、ここからです。 (1)void func(int  *N) (2)void func(int*  N) (3)void func(int*  &N) 上記は、何が違いますか? なお、当方のVS2010で同じソースを作ると、 (1)の場合、エラーになります。(func関数の*N=0のところでダウン) (2)だと、OKになります。 (3)は、なに?

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

    林晴比古さんの「新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言語入門」で勉強している初心者です。 ポインタを勉強中で、色々な例文をポインタで書けるかどうか 試しております。 上書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で返さなくても、参照できるのでないか」 と思い色々試してみましたがうまくいきません。 どうもコンパイルのエラーを確認すると型が違うので駄目なようです。 なるほどそれはそうでした… それ以外の方法も色々試してみましたが、結局うまくいきませんでした。 どのようにすればポインタでは上の文章を表現できるのでしょうか。 (あるいは表現出来ないのでしょうか) お分かりの方、よろしくお願いします。

  • 配列とポインタの使い方

    ROM領域にあるたくさんのデータの一部をRAMにコピーしたいのですが、うまくいきません。 どこがおかしいのか教えていただけないでしょうか? (例:int型の10個のデータとchar型の5個のデータをRAMへコピーする) // ROM領域に置いたテーブル const int int_table1[10]={1,2,3,4,5,6,7,8,9,0}; const char chr_table1[5]={1,2,3,4,5}; const int int_table2[10]={11,22,33,44,55,66,77,88,99,100}; const char chr_table2[5]={11,22,33,44,55}; // RAM領域 int int_data[10]; char chr_data[5]; // プロトタイプ宣言 void copy_data(int *int_p,char *chr_p); //メイン処理 | copy_data(int_table1,chr_table1); // テーブル1をRAMへコピー | | copy_data(int_table2,chr_table2); // テーブル2をRAMへコピー | // ROMデータをRAMに転送する関数 void copy_data(*int_p,*chr_p) { char i; for (i=0;i<10;i++) { int_data[i]=int_p; int_p++; } for (i=0;i<5;i++) { chr_data[i]=chr_p; chr_p++; } } コンパイルすると [Warning(ccom)] assignment from const pointer to non-const pointer ===> copy_data(int_table1,chr_table1); // テーブル1をRAMへコピー [Error(ccom)] mismatch prototyped parameter type ===> copy_data(int_table1,chr_table1); // テーブル1をRAMへコピー のワーニング&エラーになります。 どのようにしたらワーニング、エラーを直せますか? または「こうすればできる」という回答でもOKです。 よろしくお願いします。

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

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

  • 参照渡し と ポインタ渡し

    参照渡し と ポインタ渡し はどういう時に使い分けるんですか? VOID型の自作関数内でメインのブール値を書き替えたいんだけど #include <iostream.h> void ref( int &b ) { b = false; } void ptr( int *b ){ ( *b ) = true; } main(){  bool b = true;  ref( b );  cout << b;  ptr( &b );  cout << b; } だとコンパイルエラーでした。 うまくいくソースを教えてください。

  • 関数ポインタ配列の関数名を検索

    関数ポインタ配列に格納されている関数名を文字列で検索して 配列の番号を得たいのですが、どんな方法が考えられるでしょうか? void (*p_func[])(char*) = {   display,   output, }; int main() {   int fncNo;   fncNo = serchFnc( "display" ); //このserchFnc関数を作りたい   p_func[ fncNo ]( "abcd" );   return 0; } 上の例ですとdisplay関数が実行されます。 関数を50個ぐらいまで増やす予定なので追加や削除に耐えられるような 保守性のある方法が理想です。 構造体を使って関数名と検索文字列をワンセットに出来ないか考えたんですけど 適切な方法が思いつきませんでした。

  • 配列の受け渡し

    全く原因が分からないので質問させていただきます. 次のようなプログラムがあります. メイン関数で配列を宣言して, これを関数funcに渡して,func内で処理を行う. その後,メイン関数でprintf()を使って配列の内容を表示させる. 私の書いたソースは次のようになっています. int main(void) { double data[]={1.0, 2.0, 3.0, 4.0}; for(i=0; i<4; i++) { printf("%f\n", data[i]); } func(data, 4); for(i=0; i<4; i++) { printf("%f\n", data[i]); } } void func(double *f, int n) { 配列に処理を行う } メイン関数の中で, 一つ目のprintf()はちゃんと配列dataの初期値を表示します. ところが,二つ目のprintf()の手前で, 「例外」とエラーがでてきます. (コンパイルは通っています.) これが何故なのか,さっぱり分かりません. 関数func()の最後にprintf()を書いてみたところ, ちゃんと処理を行った後の正しい値が表示されます. なので,関数func()自体にバグはないように思うのです. 原因が分かる方,いらっしゃいましたら, どうぞよろしくお願いします.

  • 2次元配列とポインタの引数受け渡しについて

    2次元配列を関数に渡すときは、引数に渡す2次元配列と同じサイズを指定、もしくは2次元目のサイズのみ合わせて渡す方法がありますが、両方とも違うサイズで同じ関数を使いたいです。 最初は中身が同じで引数で受け取る2次元配列のサイズだけ、それぞれに合わせた引数を持つ関数を2つ作っていたのですが、なんだか冗長な気がしました。 そこで、2次元配列の先頭ポインタとサイズを受け取るようにすればいいのかと思い、テストとして次のプログラムを作成してみました。 #include <stdio.h> void func(unsigned char *a, int y, int x); int main(void) { unsigned char a[10][10]; func(a, 10, 10); printf("%d\n", a[7][4]); return 0; } void func(unsigned char *a, int y, int x) { int i, j; for (i = 0; i < y; i++) { for (j = 0; j < x; j++) { *(a + i*y + j) = i * j; } } } もちろんこれでも動くのですが、やはりこういう書き方はルールにはないので、コンパイルで警告が出ます。 a.c: In function ‘main’: a.c:10: warning: passing argument 1 of ‘func’ from incompatible pointer type a.c:4: note: expected ‘unsigned char *’ but argument is of type ‘unsigned char (*)[10]’ このような書き方はやはりやめたいいのでしょうか。 また、その際はサイズ別に関数を作るしかないのでしょうか。 他にいい方法があれば教えていただけると助かります。