• ベストアンサー

ポインタと多次元配列についての質問です

私の使っている本に、 『ポインタを使って多次元配列にアクセスするには、コンパイラが自動で行っていることを手作業で 行わなければなりません。たとえば、次の配列には各列に5つの要素があります。 float balance[10][5]; したがって、ポインタを使ってbalance[3][1]にアクセスするには、次のようなコードを使用 しなければなりません。 float *p; p = (float *) balance; *(p + (3*5) +1) 目的の要素に到達するには、行番号に行の要素数を掛けてから、その要素の行内での番号を 加えなければなりません。上記の例では、balanceをfloat* にキャストする必要がありました。 配列要素を手作業で指定する都合上、ポインタ演算をfloatポインタに基づいて行わなければなりません。 しかし、balanceによって生成されるポインタの型はfloatの2次元配列です。そこでキャストが 必要になるわけです。』 とあります。 【質問1】なぜ、p = (float *) balance; なのか。p = (float) *balance; ではないのか? 【質問2】本文「上記の例では………必要になるわけです。」の意味がわかりません。 未熟者の私ですがどうか教えてください。

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

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

1) pがfloat*であり balanceはfloatの配列です 両者の型が同一ではないのでキャストが必要です p = balance; では一致しないので 右辺『balance』を左辺『p』にあわせます p = (float*)balance; となります (float)*balance といった記述はしません これだと ポインタ変数balanceの指している中身をfloat型へキャストすると言う意味になります

Guchiken
質問者

お礼

さっそくの回答ありがとうございます! float*型とfloatの配列は、まったく別の型なんですね! 同じfloatだから、キャストしなくても良いんじゃないかと思って 質問しました。 回答ありがとうございました。

その他の回答 (1)

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.2

単に p を float* 型に宣言するからキャストが必要になっているだけでしょう。 float (*p)[5]; と宣言すれば、5個の要素からなる float 型の配列へのポインタになるから p = balance; と普通に代入して、 printf("%f\n",p[3][1]); と普通にアクセスできます。

Guchiken
質問者

お礼

回答ありがとうございます! 独学でプログラムの勉強をしているので、ためになります。 コードのサンプル、参考にさせていただきます! 回答ありがとうございました!

関連するQ&A

  • ポインタと二次元配列

    二次元配列a[ ][ ]の第1行の要素以後を0にするプログラムで動きます。 疑問なんですが、4行目のa[ ][4]は、なぜ[ ]のように空欄になっているんでしょうか。 また、8行目のpa=a[1];は、なぜpa=a[0];ではだめなんでしょうか。第1行は先頭行で0行目を意味しているのではないでしょうか。 #include <stdio.h> void main(void) /*ポインタと二次元配列*/ { static int a[ ][4]={{1,2,3,0}, {4,5,6,0}, {7,8,9,-999}}; int j,k,*pa; pa=a[1]; while(*pa!=-999){ *pa=0; pa++; } for(j=0;j<3;j++){ for(k=0;k<4;k++) printf("%5d",a[j][k]); printf("\n"); } }

  • 二次元配列のポインタについて教えて下さい

    今日はCの配列のポインタについて質問いたします、宜しくお願いします。 1次元の配列からは、 =================================== int *p , a={1,2,3}; p = &a; printf("%d\n" , p[1] ) ; printf("%d\n" , *p[1] ) ; ===================================== でaの値がとれますが、 二次元の配列では下のような書き方ではエラーになります。 何故でしょうか、どう書いてやればいいのでしょう。 ===============================================  printf("%d\n" , pbb[1][1] ) ;  printf("%d\n" , *pbb[1][1] ) ; =============================================== 宜しくお願いします。

  • 二次元配列のインデックスについて

    基礎的な質問かもしれませんが、ネットで調べたのですが、うまく回答が見つからなかったので、教えて下さい。 VB.netで二次元配列を扱っているのですが、この要素はどこにあるのかを知りたいのです。 一次元配列でしたら、Indexof を使えば、どこのインデックスに配置されているかが分かると思うのですが、 二次元配列の場合は、どうすればインデックス数が分かるのでしょうか。 例えば、列は0で固定だけど、どこの行にこの要素が格納されているか分からないから、行番号を知りたいと言うときです。 よろしくお願いいたします。

  • ポインタと二次元配列

    ポインタを習ったんですが、二次元配列を指定する場合はどのようにすればいいのでしょうか? また、別関数でそのポインタを呼びたいのですが。 (例) main関数 char retsu[2][2] = {{2,4},{6,8}}; char *ptr; next関数 上記でいくと「main関数内のchar retsuの二次元配列を*ptrで指定」、「next関数でmain関数で指定した*ptr(retsu[2][2])を参照したい」 という事をしたいのですが、教えて下さい。

  • 2次元配列のnew

    4x4行列のデータがいくらか書いてあるファイルから、読み込んでvector配列へ保存するプログラムを考えています。 vector配列は、float[4][4]の先頭ポインタの配列です。 宣言はこんな感じで、コンパイルエラーは出ませんでした。 vector<float[4][4]> matrix; つぎに読み込み部分で、下のような感じです。 4x4行列が見つかるたびにこれが実行されます。 GetFloatToken()は、ファイルから要素をひとつ取り出す関数です。 float m[4][4] = new float[4][4]; for(int g=0; g<4; g++) for(int r=0; r<4; r++) m[g][r]=GetFloatToken(); matrix.push_back(m); newの行とpush_backしてる行でエラーが出ました。 自分が思うに、m[4][4]のとこの、newからの受け取りの仕方が悪い気がしました。 そこで、*m[4] や **m とかにして試してみましたがうまくいきませんでした。 どうすればいいんでしょうか。 もしかして、c++では多次元配列のnewは無理なんでしょうか。 わかる方がいましたら、どうか教えてください。 補足: あとで行列の計算をするのが楽なので、float[4][4]の形は変えたくないです。 もし、多次元配列のnewが無理ということなら別の策を考えます。

  • 多次元配列とポインタ渡しについて

    多次元配列のポインタ渡しについて,自分で検索したのですがあまりにも様々で具体的な記述が無く質問させていただきました. 検索力不足もあるのでソースの提示だけでも結構ですので,ご回答お願いいたします. OS:Windows XP ソフト:VisualStudio.net2003(C++) C++プログラミング暦2ヶ月弱です. データを変換して多次元配列にデータを入れる自作の関数をつくりたいと考えています. 具体的には,a1からa2,b1からb2を10区間に分けてたデータを配列にしたいといったものです. 自分で記述した関数は以下の通りです. void Convert(float a1,float a2,float b1,float b2,unsigned short *Data){ int k; float a; float b; for(k=0;k<11;k++){ a = a1 + (a2 - a1) / 10; b = b1 + (b2 - b1) / 10; Data[k][1] = ( powf(2.0,16) * (a + 10.0) / 20; Data[k][1] = ( powf(2.0,16) * (b + 10.0) / 20; } } void main(){ float a = 10; float b = 20; unsigned short Data[11][2]; Convert(a1,a2,b1,b2,Data); ... } としています. ここでコンパイルすると, "5番目の引数をunsigned shortからunsigned short *に変換できません" となってしまいます. 配列の名前のみの部分はその配列の先頭アドレスを示すポインタであることから,自分では間違いがないと思っているのですが….

  • 2次元配列について、教えてください。

    基本的なことなのでしょうがまだよくわかっていません。 ワークシートにたとえると、1次元は縦方向(行番号方向)、二次元は横方向(列番号方向)ですよね? 列数、行数にあたるのが1次元、二次元それぞれの添字ですよね? そしてセルに当たるのが「要素」ですよね? 以上の解釈があっていたら、 1.A列やB列にあたるものはなんと呼ぶのでしょうか? 2.1行目や2行目にあたるのはなんと呼びますか? 3.ワークシートで行や列を削除するような感じで2次元配列の行や列にあたるものを削除することはできますか? 4.UBound関数は、配列の大きさを調べられますが、この大きさは添字です。ワークシートのCells(65536,1).End(xlUp)Rowのように実際にデータがどこまで入っているか調べられますか? 教えてください。 前提とした解釈自体が違っていたらそれもご指摘ください。

  • ポインタ型配列のポインタを構造体のポインタ変数に格納する方法教えて!_ver2

    int型の配列は構造体のポインタ型のint型変数にはキャストすればうまくコンパイルが通りますが、同じ方法でfloat型の配列は構造体のポインタ型のfloat型変数にはキャストしてポインタの値を入れてもうまくコンパイルできず困っています。ちなみにコンパイルエラーは「互換でない型変換」と表示されます。 返答のほど、よろしくお願いいたします。 #include<stdio.h> #include<malloc.h> float time[] ={2.2, 2.3, 2.4}; int time2[] ={2, 2, 2}; struct timelist{ float *time; int *time2; struct timelist *next; }*head; void main(void) { struct timelist *p; p = (struct timelist *)malloc(sizeof(struct timelist)); p -> time = (float *)time[0]; p -> time2 = (int *)time2[0]; printf("time = %f\n", p -> time); printf("time2 = %d\n", p -> time2); }

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

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

  • 二次元配列が、勝手に一次元配列になってしまう

    Excelのマクロで、二次元配列を格納したバリアント型を戻り値とする関数を作ったのですが、… 二次元型配列のひとつの要素数が1の時、受け取ったバリアント型変数は、一次元配列になっています。 列ベクトルなら、それもありかな~と思うのですが、なんで、行ベクトルまで、一次元配列にするんだよ~って、困っています。 シートから関数を呼んだ場合は、列ベクトルは列ベクトル、行ベクトルは行ベクトルとして、表示されるので、マクロの中で関数を呼び出した場合も、行列の情報を保持できる方法があるんじゃないかと思ったのですが。 どなたか、ご教示頂けるとありがたいです。 よろしくお願いします。