#include <stdio.h>
int main(void){
int *ptr;
printf("the value of ptr is %p",ptr);
}
これは私に0x7fffbd8ce900
を与えます。これはわずか6バイトです。それは8バイト(64ビット)でなければなりませんか?ポインタのアドレスが64ビットの場合、印刷時に6バイトと表示されるのはなぜですか?
#include <stdio.h>
int main(void){
int *ptr;
printf("the value of ptr is %p",ptr);
}
これは私に0x7fffbd8ce900
を与えます。これはわずか6バイトです。それは8バイト(64ビット)でなければなりませんか?ポインタのアドレスが64ビットの場合、印刷時に6バイトと表示されるのはなぜですか?
6バイトのアドレスは仮想アドレス(実際の物理アドレスのオフセット)にすぎないためです。物理的アーキテクチャ(例えばX86)では、メモリは、16ビットのセグメントセレクタを変更することなく、単一のインデックスレジスタによってアドレス指定され得る部分に分割される。 X86-CPUのリアルモードでは、セグメントは常に16ビット(2バイト)のセグメントセレクタを使用しています。このセレクタは、プログラムの実行を開始したときにオペレーティングシステムによって動的に決定されます(つまり、 )。
したがって、あなたの変数は48ビットのアドレス0x7fffbd8ce900、及びプログラムを持っている場合、セグメント・セレクタは08afオフセット有し、変数の実アドレスは、(0x08afが< < 48)+ 0x7fffbd8ce900 = 0x08af7fffbd8ce900、64であり、これは-ビット。あなたは `ptr`を初期化しませんので、あなたが印刷している値は、ゴミである x86 memory segmentation
Wow、あなたの答えはメモリアーキテクチャの私の目を開いて、cやlinuxのコマンドラインツールを使用するような実際のメモリ内容の内容を検査する方法はありますか? – mko
この回答は間違っています。最新のオペレーティングシステムでは、セグメンテーションなしでフラットな仮想アドレス空間が使用され、64ビットモード(「ロングモード」)ではセグメンテーションがサポートされていません。問題の16ビットは、セグメントセレクタの場所ではありません。 – Wyzard
いいえ、これは8086リアルモード(seg:オフセットアドレスが 'seg << 4 + offset'にマップされています)と仮想メモリを混在させています。ちょうど全く間違っている。 –
これはちょうど最初の2バイトがゼロであることを意味します(ちなみに、現時点ではx86-64チップのために保証されていますが、ポインタが初期化されていないため、この場合は何も意味しません)。 %p
は他の数値型と同様に先行ゼロを切り捨てることができます。しかし、%016p
はそうではありません。これは、正常に動作する必要があり:
printf("the value of ptr is %016p", ptr);
ポインタが64ビット、current processors actually only support 48 bitsので、アドレスの上位2バイトであるが、常に(拡張に署名することにより)のいずれか0000、またはFFFFです。
将来的に48ビットが十分でなくなると、新しいプロセッサは56ビットまたは64ビット仮想アドレスのサポートを追加することができ、既存のプログラムはすでに64ビットを使用しているため追加のスペースを利用できますビットポインタ。
0x00007fffdb8ce900 – xiefei
:
はさらにPLSに回し読み。有効なアドレスが含まれていると仮定する理由はありません。 –