0

コンパイル:

#include <stdlib.h>


void f(int ** v)
{
}

int main()
{
    int v[2][3];
    f(v);
    return 0;
}

失敗した:

g.cpp:13:8: error: cannot convert ‘int (*)[3]’ to ‘int**’ for argument ‘1’ to ‘void f(int**)’

しかし、次の変更が渡されました。

#include <stdlib.h>


void f(int ** v)
{
}

int main()
{
    int * v[2];
    f(v);
    return 0;
}

配列のより深い次元はコンパイル時に解決する必要があるように私には思えました、そして誰かがそれについてもっと詳しく説明することができますか?

4

2 に答える 2

2

C および C++ は、配列をポインターに自動的に変換します。エラーは、この強制が 1 回だけ (つまり、最初のレベルでのみ) 発生するために発生します。これはint [10]強制されることを意味しint *ます; int [10][10]しかし、せいぜいに強制することができint *[10]ます。

その理由は、メモリ レイアウトに関係しています。おわかりのように、 is が型の場合にa[i]変換されます (ポインターへの追加は、スケーリングなしで直接追加すると仮定します)。がタイプの場合、 に変換されます。したがって、最初の要素のアドレスを取得することで、型の値を強制的に型の値にすることができます。この場合、メモリ レイアウトは互換性があります。*(a + sizeof(T) * i)aT *aT [N]a[i]*(&a[0] + i)T [N]T *

ただし、2 次元配列a(タイプT [2] [4]など) は、ダブル ポインター (タイプ ) とは異なる方法で格納されますT **。最初のケースでは、4 つの要素がメモリT [0][0]に配置され、その後にtoなどが続き、モジュロ アラインメントが行われます。2 番目のケースでは、一連の (への) ポインターが次々に配置されています。最初のケースでは、は に下げられ、2 番目のケースでは に下げられます。メモリ レイアウトには互換性がありません。 T [0][3]T [1][0]T [1][3]Ta[i][j]*(&a[0][0] + sizeof(T) * 4 * i + sizeof(T) * j)*(*(a + sizeof(T) * i) + sizeof(T) * j)

于 2013-01-10T21:23:49.970 に答える
0

int へのポインターは、配列へのポインターとは異なります。

を実行するとき、アドレスをインクリメントするかv++どうかをコンパイラに通知する必要があります。sizeof(int)array_length*sizeof(int)

于 2013-01-10T19:12:44.383 に答える