2016-04-12 7 views
1

にこの配列(2D)にアクセスしようとしているとき、何が間違っているいけない、私はこの配列内の四つの要素を持っているときは、私はC++以下

#include <iostream> 
using namespace std; 

int foo(int **a){ 
    cout<<*(a+3)<<endl; 
    return 1; 
} 

int main(){ 
    int a[2][2] = {{1,2},{3,4}}; 
    std::cout << sizeof(a); 
    foo((int **)a); 
} 

を実行しようとしているコードです。 *(a + 3)の値は、そのアドレスを返す代わりに値4を返します。そのアドレス(つまり**(a + 3))を逆参照しようとすると、segfault 11を返します。

+3

可能な複製を使用することができます-pointer](http://stackoverflow.com/questions/8203700/conversion-of-2d-array-to-pointer-to-pointer) – smead

+0

コンパイルするには、そのコードに不適切なキャストを壊す必要があったあなたの最初のヒントが間違っている。 – WhozCraig

答えて

0

int**int*が得られます。ただし、値4の位置を参照解除すると、int*と解釈されます。だからこそ、coutはアドレスとして書式を設定するので、0x4を印刷します。 int*をパラメータとして使用してみてください:

#include <iostream> 
using namespace std; 

int foo(int *a){ 
    cout<<*(a+3)<<endl; 
    return 1; 
} 

int main(){ 
    int a[2][2] = {{1,2},{3,4}}; 
    std::cout << sizeof(a); 
    foo((int *)a); 
} 


これは、このコードを修正する方法の単なる例であり、正しい方法ではありません。 @rodrigoが答えのコメントで述べたように、intのサイズがポインタのサイズと等しくない場合、これはうまくいきません。私はちょうどあなたがそれが1つと解釈されているので、それがアドレスを印刷していると思った理由をあなたに示すことを望んでいました。

0

逆参照が多すぎます。 aは既に配列の最初の要素を指しています。だから** aは配列の最初の値を値の代わりにアドレスとして扱います。試してみてください

foo((int *)a) 
6

実際には、整数の配列を定義しています。それは整数の配列へのポインタに崩壊することができますが、ではなく、は整数のポインタへのポインタに崩壊します。

それはあなたのメモリレイアウトを描く場合に役立ちます。

int (*pa)[2] = a; 

+---------+---------+---------+---------+ 
| pa[0]   | pa[1]   | 
+---------+---------+---------+---------+ 
| 1 | 2 | 3 | 4 | 
+---------+---------+---------+---------+ 

注方法sizeof(*pa) = 2 * sizeof(int):あなたは、それはへのポインタの配列-の整数に崩壊させた場合

+---------+---------+---------+---------+ 
| a[0][0] | a[0][1] | a[1][0] | a[1][1] | 
+---------+---------+---------+---------+ 
| 1 | 2 | 3 | 4 | 
+---------+---------+---------+---------+ 

を。これらの各値は、決してポインタへのポインタに、整数へのポインタに崩壊することができます:あなたは、整数へのポインタに虫歯へのポインタの配列-の整数をキャストすることができ、とにかく

int *p = pa[0]; 

int *p = (int*)a; 
std::cout << p[3] << std::endl; 
std::cout << *(p + 3) << std::endl; 

メモリは次のようになります:

+---------+---------+---------+---------+ 
| p[0] | p[1] | p[2] | p[3] | 
+---------+---------+---------+---------+ 
| 1 | 2 | 3 | 4 | 
+---------+---------+---------+---------+ 

しかし、あなたがint**にそれをキャストする場合は、理由は私には、意味のない値を取得します四つの値に直接アクセスしますmoryポインタはなく、整数だけです。

+0

実際には値はa + 3の位置にあります。なぜなら、aも最初の要素の位置ですから、特にコードの問題は、印刷時に数値ではなくアドレスとしてフォーマットされてしまうことです。 –

+0

@ComradeBearabyte: 'sizeof(int *)!= sizeof(int)'以外の場合。それから、あなたは正しい場所から抜け出すでしょう。 – rodrigo

+0

あなたはそうだ、それについて実際には考えなかった –

2

配列はポインタではありません。はい、それはそれが1であることを意味しないポインタに崩壊することができます。あなたは2D配列を渡したいなら、あなたは

int foo(int a[][2]); 

を使用するかは、任意のサイズの配列を取りたいならば、あなたはポインタにするために2次元配列の[変換の

template<std::size_t N> 
int foo(int a[][N]); 
関連する問題