RINGKASAN SINGKAT
(yang juga akan saya tempatkan di atas):
(0) Memikirkan pointer sebagai alamat seringkali merupakan alat pembelajaran yang baik, dan seringkali implementasi aktual untuk pointer ke tipe data biasa.
(1) Tetapi pada banyak, mungkin sebagian besar, kompiler pointer ke fungsi bukan alamat, tetapi lebih besar dari alamat (biasanya 2x, kadang-kadang lebih), atau sebenarnya pointer ke struct dalam memori daripada berisi alamat fungsi dan hal-hal seperti kolam konstan.
(2) Pointer ke anggota data dan pointer ke metode seringkali lebih aneh.
(3) Kode x86 lawas dengan masalah pointer FAR dan NEAR
(4) Beberapa contoh, terutama IBM AS / 400, dengan "penunjuk gemuk" yang aman.
Saya yakin Anda dapat menemukan lebih banyak.
DETAIL:
UMMPPHHH !!!!! Banyak jawaban sejauh ini merupakan jawaban "programmer weenie" yang cukup tipikal - tetapi bukan compiler weenie atau perangkat keras weenie. Karena saya berpura-pura menjadi perangkat keras weenie, dan sering bekerja dengan alat compiler, izinkan saya memasukkan dua sen saya:
Pada banyak, mungkin sebagian besar, kompiler C, sebuah pointer ke data bertipe T
, pada kenyataannya, adalah alamat T
.
Baik.
Tetapi, bahkan pada banyak kompiler ini, pointer tertentu BUKAN alamat. Anda dapat mengatakan ini dengan melihat sizeof(ThePointer)
.
Sebagai contoh, pointer ke fungsi terkadang jauh lebih besar dari alamat biasa. Atau, mereka mungkin melibatkan tingkat tipuan. Artikel inimemberikan satu deskripsi, yang melibatkan prosesor Intel Itanium, tetapi saya telah melihat yang lain. Biasanya, untuk memanggil fungsi, Anda harus tahu tidak hanya alamat kode fungsi, tetapi juga alamat kumpulan fungsi konstan - wilayah memori tempat konstanta dimuat dengan instruksi beban tunggal, bukan dari kompiler yang harus menghasilkan konstanta 64 bit dari beberapa instruksi Load Immediate dan Shift dan OR. Jadi, daripada satu alamat 64 bit, Anda membutuhkan 2 alamat 64 bit. Beberapa ABI (Application Binary Interfaces) memindahkan ini sekitar 128 bit, sedangkan yang lain menggunakan tingkat tipuan, dengan penunjuk fungsi sebenarnya menjadi alamat deskriptor fungsi yang berisi 2 alamat aktual yang baru saja disebutkan. Mana yang lebih baik? Tergantung pada sudut pandang Anda: kinerja, ukuran kode, dan beberapa masalah kompatibilitas - seringkali kode mengasumsikan bahwa pointer dapat dilemparkan ke panjang atau panjang, tetapi juga dapat mengasumsikan bahwa panjangnya persis 64 bit. Kode semacam itu mungkin tidak sesuai standar, namun demikian pelanggan mungkin menginginkannya berfungsi.
Banyak dari kita memiliki kenangan menyakitkan arsitektur Intel x86 yang lama, dengan POINTER DEKAT dan POINTER JAUH. Untungnya ini hampir punah sekarang, jadi hanya ringkasan cepat: dalam mode real 16 bit, alamat linear yang sebenarnya
LinearAddress = SegmentRegister[SegNum].base << 4 + Offset
Padahal dalam mode terproteksi, mungkin saja
LinearAddress = SegmentRegister[SegNum].base + offset
dengan alamat yang dihasilkan diperiksa terhadap batas yang ditentukan di segmen. Beberapa program yang digunakan tidak benar-benar standar C / C ++ deklarasi pointer FAR dan NEAR, tetapi banyak yang hanya mengatakan *T
--- tetapi ada switch kompilator dan linker jadi, misalnya, kode pointer mungkin dekat pointer, hanya offset 32 bit terhadap apa pun yang ada di register CS (Segmen Kode), sedangkan pointer data mungkin adalah pointer FAR, menentukan nomor segmen 16 bit dan offset 32 bit untuk nilai 48 bit. Sekarang, kedua jumlah ini tentu terkait dengan alamat, tetapi karena mereka tidak ukuran yang sama, yang mana dari mereka adalah alamat? Selain itu, segmen juga membawa izin - baca-saja, baca-tulis, dapat dieksekusi - di samping hal-hal yang terkait dengan alamat aktual.
Contoh yang lebih menarik, IMHO, adalah (atau, mungkin, adalah) keluarga IBM AS / 400. Komputer ini adalah salah satu yang pertama menerapkan OS di C ++. Pointer pada machime ini biasanya 2X ukuran alamat yang sebenarnya - misalnya sebagai presentasi inimengatakan, 128 bit pointer, tetapi alamat sebenarnya adalah 48-64 bit, dan, sekali lagi, beberapa info tambahan, apa yang disebut kemampuan, yang memberikan izin seperti baca, tulis, serta batas untuk mencegah buffer overflow. Ya: Anda dapat melakukan ini sesuai dengan C / C ++ - dan jika ini ada di mana-mana, PLA Cina dan mafia slavia tidak akan meretas ke banyak sistem komputer Barat. Namun secara historis sebagian besar pemrograman C / C ++ telah mengabaikan keamanan untuk kinerja. Yang paling menarik, keluarga AS400 memungkinkan sistem operasi untuk membuat pointer aman, yang dapat diberikan pada kode yang tidak terprivasi, tetapi yang tidak bisa dipalsukan atau diubah oleh kode yang tidak terprivasi. Sekali lagi, keamanan, dan meskipun standar memenuhi syarat, banyak kode C / C ++ yang tidak memenuhi standar yang ceroboh tidak akan berfungsi dalam sistem yang aman. Sekali lagi, ada standar resmi,
Sekarang, saya akan keluar dari kotak sabun keamanan saya, dan menyebutkan beberapa cara lain di mana pointer (dari berbagai jenis) sering tidak benar-benar alamat: Pointer ke anggota data, pointer ke metode fungsi anggota, dan versi statisnya lebih besar daripada alamat biasa. Seperti yang dikatakan oleh posting ini :
Ada banyak cara untuk menyelesaikan ini [masalah yang terkait dengan inheitance tunggal versus ganda, dan warisan virtual]. Inilah cara kompiler Visual Studio memutuskan untuk menanganinya: Sebuah pointer ke fungsi anggota dari kelas multiply-inherited benar-benar sebuah struktur. "Dan mereka melanjutkan dengan mengatakan" Casting pointer fungsi dapat mengubah ukurannya! ".
Karena Anda mungkin dapat menebak dari pontificating saya pada (dalam) keamanan, saya telah terlibat dalam proyek perangkat keras / perangkat lunak C / C ++ di mana pointer diperlakukan lebih seperti kemampuan daripada alamat mentah.
Saya bisa terus, tapi saya harap Anda mendapatkan ide.
RINGKASAN SINGKAT
(yang juga akan saya tempatkan di atas):
(0) memikirkan pointer sebagai alamat seringkali merupakan alat pembelajaran yang baik, dan seringkali implementasi aktual untuk pointer ke tipe data biasa.
(1) Tetapi pada banyak, mungkin sebagian besar, kompiler pointer ke fungsi bukan alamat, tetapi lebih besar dari alamat (biasanya 2X, kadang-kadang lebih), atau sebenarnya pointer ke struct di memori daripada berisi alamat fungsi dan hal-hal seperti kolam konstan.
(2) Pointer ke anggota data dan pointer ke metode seringkali lebih aneh.
(3) Kode x86 lawas dengan masalah pointer FAR dan NEAR
(4) Beberapa contoh, terutama IBM AS / 400, dengan "penunjuk gemuk" yang aman.
Saya yakin Anda dapat menemukan lebih banyak.