2016-04-28 14 views
1

次のようにして、C++で2次元配列を作成できます。しかし、私はメモリアドレッシングを理解するのに困っています。私はgccのバージョン4.7.1(TDM-1)コンパイラを使用して走ったC++の動的2次元配列のアドレス

(私はメモリ位置の小数点以下の値を印刷しようとするところに私のコードの最後の行に注意してください。)

#include <cstdio> 
#include <iostream> 

using namespace std; 

#define rowSize 3 
#define colSize 4 


int main(){ 
    int ** p; 

    p = new int*[rowSize]; 

    for(int i = 0; i < rowSize; i++){ 
     p[i]= new int[colSize]; 
    } 

    printf("the size of int**: %d\n", sizeof(int**)); 
    printf("the size of int*: %d\n", sizeof(int*)); 
    printf("the size of int: %d\n\n", sizeof(int)); 



    printf("%d %d", p[0], p[1]); 
    return 0; 
} 
私私の窓のプログラムは、10-64ビットマシンです。

int型のサイズ**:4

int型のサイズ*:4

int型のサイズ:4

8135000ここ

は、サンプル出力です8135024

ここに私の2つの質問があります:

  1. 16(= 4 * 4)ではなく24でアドレスが異なるのはなぜですか? intのサイズは4で、4列あります。彼らは16歳までに違いないでしょうか? 私は、C++の構造体でバイトパディングを知っています。このような何かの背後にある理由はありますか?

    #define colSize 5、再コンパイルして、もう一度プログラムを実行した:

  2. は、私は5にcolSizeを変えてみました。

    サンプル出力:

the size of int**: 4 

the size of int*: 4 

the size of int: 4 


7151960 7151992 

バイトのパディングが理由であった場合にアドレスが32だけ異なる。この時間は、5列は5×4 = 20バイトを必要とするであろう。この場合、4バイトのパディングで十分であり、アドレスもこの場合24だけ異なるはずです。

この場合、なぜ32で違いますか?

+0

どのような回答がお望みですか? gccの実装の詳細を説明していますか?あるいは、「質問がどのようにレイアウトされているかは保証されていません。あなたはそれらについて予測するべきではありませんが、XとYに頼らなければならない場合は、これを使用してください...」とすれば十分でしょうか? – VolkerK

+0

実際の2次元配列で同じことを試してください:int p [3] [4]; –

+0

はい、その差を計算することができます。しかし、私は 'new int [colSize]'が何らかのパターンでアドレスを返すかどうかを理解することにもっと興味がありました。 –

答えて

2
  1. メモリ割り当て動作の結果alignof(std::max_align_t)が-alignedれます。あなたのケースでは、alignof(std::max_align_t)はおそらく8です。
  2. ほとんどの実装では、いくつかの内部簿記のために配列の隣に目に見えない量のsizeof(std::max_align_t)バイトが割り当てられています。 * 4 4 + 8 = 24、第2 8.
    のすでに複数:* 5 4 + 8 = 28、丸みを帯びたあなたのケースでは、それはおそらく、最初のケースでそう8.

の大きさを持っていますさ最も近い乗算の8 = 32までです。

コンパイラは、増加するアドレスを返したり、いくつかのパターンを実行する義務はありません。それはちょうどあなたの場合に行うことが最も簡単なことが起こった。

+0

私は 'printf("%d "、size_t);'を使って、出力に4を得ました。しかし、おかげさまで、私は毎回同じ違いを見つけたのが不思議でした。 –

+0

@AhsanTariqueは私の答えを少し正確にするように修正しました。私はsize_tが32bitマシンの最大のアライメントタイプではないことを忘れていました –

-1

あなたはCを書い++が、C.されていないあなたがC++としてこれをタグ付けしたように、私はあなたがC++をしたいと仮定します...

現代のC++はRAIIを使用し、大幅ライブラリ標準コンテナを使用して、物事の並べ替えを簡素化します。私はこれは本当にあなたの質問への答えではありません承知していますが、私はあなたのコードを書き換えることをお勧め:あなたのp[i] arryas細胞内

#include <vector> 
#include <cstdio> 
int main() 
{ 
    int rowsize = ...; 
    int colsize = ...; 

// allocating 
    std::vector<std::vector<int>> vec(rowsize); 
    for(auto e: vec) 
     e.resize(colsize); 

// filling with values 
    vec.at(row).at(col) = 123; 
// printing values 
    std::cout << vec.at(row).at(col) << std::endl; 
} 
1

アドレスがnewオペレータ

pで定義されています[i] =新しいint [colSize];

この演算子はヒープから任意のアドレスを返すことができ、これは配列のサイズに依存しません。

大きな1次元配列(コンパイラはarray[][])を作成し、2つの次元を1つの次元にマッピングすることができます。

int* arr2d = new int[colSize*rowSize]; 
//Retrieve value from Row3 Col2 
int nRow3Col2 = arr2d[2 + 3 * colSize]; 
+0

アドレスは変わりますが、実行ごとに同じ長さの違いがあるようです。だから私は、アドレスの代わりにパターンがランダムかもしれないと思った。 –

+0

'new'演算子の実装に依存します(BTWにオーバーロードされる可能性があります)。とにかくaddresesは保証されません。また、 'Release'モードでコンパイルし、その違いを観察してください。 –

+0

リリースモードについてあなたが言ったことを理解できませんでした。私はそれをgoogleにしようとし、resutlsの一つでこれを見つけた。 [リンク](http://stackoverflow.com/questions/11253334/how-to-debug-in-release-mode)私は質問で答えたメソッドを試してください? –