2017-01-02 11 views
0
#include<stdio.h> 

int main() 
{ 
int arr[3] = {2, 3, 4}; 
char *p; 
p = arr; 
p = (char*)((int*)(p)); 
printf("%d, ", *p); 
p = (int*)(p+1); 
printf("%d", *p); 
return 0; 
} 

p =(int *)(p + 1)ではありません。配列の次の要素を指していますか? (viz 3?)したがって、出力は2,3でなければなりません。しかし、出力は2,0です。どうして?なぜ2,3の代わりに出力2,0ですか?

+3

いいえ、 'p'は' char * 'ポインターです。 'char *'ポインタに1を加えることは、 'int *'ポインタに1を加えることと同じではありません。 –

+0

リトルエンディアンマシン。 –

+1

それは私が推測するエンディアンです.....あなたはpを増分し、次のバイトに移動します...そして、あなたのMSBareが最初に格納されているので0です。 – coderredoc

答えて

3

あなたは次charメモリ位置へcharポインタpが増加している - それは、int 4つのメモリ位置を取ること(他はゼロで埋め)数2ため0パディングバイトの一つです。

つまり、int *p;の場合はchar *p;を置き換えて、すべてのキャスティングをp = (char*)((int*)(p));で取り除くと、プログラムが正常に動作するはずです。 このような電流で使用されるように、リトルエンディアンメモリモデルでは(それは、有用ではないキャスティングを維持作業する増分が整数ポインタではなく、文字ポインタで発生するようにp = (char *) (((int *) p) + 1);ためp = (int*)(p+1);を変更する)

PCのint型はそれぞれメモリ内で4バイトをとります。最初のものは最も重要ではありません(したがって、256(2^8)より小さい数の場合は整数です)。

あなたは、メモリ内のこのバイト配列を有する:あなたは "CHAR *" ポインタを使用する場合'02 00 00 00 03 00 00 00 04 00 00 00' は

、コンパイラは、charのサイズを知っていますデータ要素は1バイトです。それを増やすと、隣接するバイトに進むだけで、 "0"になります。

"printf"呼び出しでは、 "char * p"(1バイトの数字は0)のコンテンツにアクセスし、コンパイラは "printf"の呼び出しでその値を埋め込みます。 "0"と表示されますが、他のコンパイラやシステムでは、printfの "%d"パラメータで予想されるバイトのうち3つがそこに存在しないため、ガベージまたはセグメンテーションが出力される可能性があります。

+1

3と4はちょうど同じくらい簡単に7と8になることができます。ここではエンディアンのみが示唆されています。 – StoryTeller

+0

ガベージまたはセグメンテーションフォルトに関するご意見が間違っています。単一バイトは評価され、 'printf'のような省略記号を持つ関数の引数に適用されるデフォルトの引数昇格規則の下で' int'に変換されます。 –

2

これは、pがデータ型のポインタの種類が間違っているからです。

pを増やすと、その値は1 * sizeof(int)だけ増加し、1 * sizeof(char)で増加します。

2 0 0 0 3 0 0 0 4 0 0 0 
^------ p 

pが第1の設定がある場合は

2 0 0 0 3 0 0 0 4 0 0 0 

は、あなたがこれを持っている:intを想定し

バイトレベルでarrの内容は、4バイト、リトルエンディアンのバイト順序ですp(int*)(p + 1)に設定すると、pが1だけ増えます。キャストはここでは役に立ちません。だから、これを取得する:

2 0 0 0 3 0 0 0 4 0 0 0 
    ^------ p 

だから、逆参照pは、そのメモリ位置での1つのバイトを読み込み、あなたは0を持っています。

あなたがintのサイズによってpをインクリメントしたい場合は、あなたがp自体をキャストする必要があり、その後、それに追加します。

p = `(int*)(p) + 1` 

次に、あなたが期待する結果を得るでしょう。

1

ポインタの種類が特定のデータ型のポインタに1を添加Pointer Arithmatics

のために指してのデータのと同じデータ型でなければならないが、メモリのバイト数を追加する理由でありますポインタが現在ポイントしている今では、P +(X-バイト)アドレスを指すされ、それは、例えば

ためにそのアドレス

であなたの値を与える参照デあなたのポインタを宣言するアドレスタイプintのように

int *p = new int[5]; 

配列内の各要素(配列に入力した場合)は、メモリ内に4バイト(アドレス用語と32ビットシステムの場合)の領域がメモリに格納されます。 1p = p+1のようにポインタに追加すると、配列内の次の要素(4バイト先のアドレス)に移動します。 他のタイプのポインタの場合も同じですが、ポインタ自体のデータ型のアドレス空間の多くのバイトにジャンプするという違いがあります。

ポインタは単にメモリを指していると言うことができるので、ポインタの型を宣言しても何の違いもありません。はい、それは本当ですが、ポインタを使用しているときにはいつでも推薦されませんが、ポインタは非常に確実に使用されます。メモリアドレスの正確なジャンプのために、ポインターが指定されたデータと同じデータ型のポインタを宣言します。

+0

** C **言語には**新しい**が追加されました – Michi

関連する問題