1

私は現在cを学んでおり、ポインターを勉強しています。私はいくつかの例を読んで、これを思いつきました:

   #include <stdio.h>

   int main ()
   { 
      float balance[10][5];
      float *p;

      p = (float *) balance;

      *(p + 16) = 200.0; //init the balance[3][1] with the value 200.0
       printf("%f\n", balance[3][1]); 
       return 0;    
   }

私の質問はこれです。でバランスをキャストする必要があるのはなぜ(float *)ですか? これは、配列が 2 次元だからでしょうか。ポインタも2次元ですか?だから私はそれを1次元に変換する必要がありますか?

4

5 に答える 5

3

(float *) でバランスをキャストする必要があるのはなぜですか?

これはpis が型であるのfloat *に対し、balanceis はfloat (*)[5]ポインターに減衰した後の型であるためです。

これは、配列が2次元だからですか?

はい。

ポインタも2次元ですか?

balanceに減衰しfloat (*)[5]ます。

だから私はそれを1次元に変換する必要がありますか?

はい。

于 2013-10-20T15:36:52.733 に答える
1

このコードは醜いハックであり、現在、そして将来このコードを見るために戻ってきたときに混乱を招くだけです. ポインター演算の背後にある考え方は、配列へのアクセスを難しくするのではなく、簡単にすることです。変えたら

    float *p;

    float **p;

ポインターは二重ポインターになりました。つまり、間接演算子 (*) を 1 回使用すると、別のポインターが得られます。作成した配列は次のようになります。

[0,0][0,1][0,2][0,3][0,4]
[1,0][1,1][1,2][1,3][1,4]
[2,0][2,1][2,2][2,3][2,4]
[3,0][3,1][3,2][3,3][3,4]
[4,0][4,1][4,2][4,3][4,4]
[5,0][5,1][5,2][5,3][5,4]
[6,0][6,1][6,2][6,3][6,4]
[7,0][7,1][7,2][7,3][7,4]
[8,0][8,1][8,2][8,3][8,4]
[9,0][9,1][9,2][9,3][9,4]

2 レベルの間接参照があるため、最初のポインターは行を指し、2 番目のポインターは列を指します。インダイレクションは逆方向に行われるため、ポインター表記では最も内側の要素が配列表記で最も左にある要素になります。

arr[ROW][COL] === *(*(p + ROW) + COL) 

要素にアクセスしたい場合は、配列表記arr [ROW][COL] を使用するか、ポインター演算を使用してアクセスできます。二重ポインターでは、2 つのレベルの間接参照があります。だからあなたが使用しなければならなかったのに対し

    p = (float *) balance;
    *(p + 16)

必要な場所を取得するには、実際には(私の意見では)単純に書く方がはるかに簡単です

    p = balance;
    *(*(p + 3) + 1)

これは、ポインター演算を配列のインデックス付けと同様に使用しているため、ポイントしたい要素を一目で簡単に判断できるからです。

二重ポインターを単一のポインターにキャストする限り、最初に二重ポインターを処理する方が本当に簡単です。それが配列の名前のすべてです。

    int arr[ROW][COL] = {0};
    int **p_arr = arr; /* Valid operation. arr without array notation is a double pointer */
于 2013-10-20T16:13:08.017 に答える
0

この例は、配列がメモリに割り当てられる方法を示しています。2 次元配列は、最初の行の後にメモリ内の配列の 2 番目の行がある行によって割り当てられます。配列のメモリは 1 つのエクステントとして割り当てられるため、1 次元配列として解釈できます。

この例の配列には、実際には 50 個の要素 (10 * 5) があります。行はメモリ内で順番に格納されるため、balance[3][1] 要素の位置は 3 * 5 + 1、つまり 16 として計算できます。したがって、メモリのその範囲を 1 次元と見なす場合は、配列の場合、対応する要素は p[16] または (同じ) *(p + 16) と記述できます。

このような 2 次元配列の解釈の便利なトリックの 1 つは、2 次元配列のソートに適用できます。標準の並べ替え関数を使用して、2 次元配列を 1 次元配列として並べ替える方がはるかに簡単です。

于 2013-10-20T15:54:17.637 に答える
0

(float *) でバランスをキャストしなければならない理由

する必要はありませんprintf() . フラット アクセスと多次元アクセスを組み合わせることはお控えください。

于 2013-10-20T15:58:45.813 に答える
-1

ここで、変数「balance」には、2 次元配列のベースアドレスが格納されます。

ポインタとは何ですか?アドレスを格納する変数をポインタと呼びます

右!!

「p」は浮動変数のアドレスを格納する単一の浮動ポインターですが、ここでは「balance」は浮動配列変数です。

あなたがしたことは、2D配列変数を1D配列としてポインターに型キャストすることです...つまり、2D配列である「バランス」で割り当てたポインター変数「p」に従って、1D配列になりました.. .

ポインタlykをこれに割り当てる場合

float **p;

それから

p=バランス; は有効なステートメントであり、ポインターはこれを 2D 配列として扱います。

于 2013-10-20T15:43:47.570 に答える