Dalam C (atau C ++ dalam hal ini), pointer menjadi spesial jika memiliki nilai nol: Saya disarankan untuk mengatur pointer ke nol setelah membebaskan memori mereka, karena itu berarti membebaskan pointer lagi tidak berbahaya; ketika saya memanggil malloc itu mengembalikan sebuah pointer dengan nilai nol jika tidak bisa mendapatkan saya memori; Saya menggunakan if (p != 0)
sepanjang waktu untuk memastikan petunjuk yang diberikan valid, dll.
Tetapi karena pengalamatan memori dimulai dari 0, bukankah 0 hanya sebagai alamat yang valid seperti yang lainnya? Bagaimana 0 digunakan untuk menangani pointer nol jika itu masalahnya? Mengapa angka negatif bukan nol?
Edit:
Sekelompok jawaban bagus. Saya akan meringkas apa yang telah dikatakan dalam jawaban yang diungkapkan saat pikiran saya sendiri menafsirkannya dan berharap komunitas akan mengoreksi saya jika saya salah paham.
Seperti semua hal lain dalam pemrograman, ini adalah abstraksi. Hanya sebuah konstanta, tidak benar-benar terkait dengan alamat 0. C ++ 0x menekankan hal ini dengan menambahkan kata kunci
nullptr
.Ini bahkan bukan abstraksi alamat, itu adalah konstanta yang ditentukan oleh standar C dan compiler dapat menerjemahkannya ke beberapa nomor lain selama itu memastikan itu tidak pernah sama dengan alamat "sebenarnya", dan sama dengan pointer nol lainnya jika 0 bukan nilai terbaik untuk digunakan untuk platform.
Jika ini bukan abstraksi, seperti yang terjadi di masa-masa awal, alamat 0 digunakan oleh sistem dan terlarang bagi pemrogram.
Saran nomor negatif saya adalah curah pendapat yang sedikit liar, saya akui. Menggunakan bilangan bulat bertanda untuk alamat sedikit boros jika itu berarti bahwa selain dari penunjuk nol (-1 atau apa pun), ruang nilai dibagi secara merata antara bilangan bulat positif yang membuat alamat valid dan bilangan negatif yang hanya terbuang percuma.
Jika ada angka yang selalu dapat diwakili oleh tipe data, itu 0. (Mungkin 1 juga. Saya memikirkan integer satu-bit yang akan menjadi 0 atau 1 jika unsigned, atau hanya bit yang ditandatangani jika ditandatangani, atau dua bit integer yang mana akan menjadi [-2, 1]. Tapi kemudian Anda bisa menggunakan 0 menjadi null dan 1 menjadi satu-satunya byte yang dapat diakses dalam memori.)
Masih ada sesuatu yang belum terselesaikan di benak saya. Pointer pertanyaan Stack Overflow ke alamat tetap tertentu memberi tahu saya bahwa meskipun 0 untuk pointer nol adalah abstraksi, nilai pointer lain belum tentu. Ini mengarahkan saya untuk memposting pertanyaan Stack Overflow lainnya, Dapatkah saya mengakses alamat nol? .
if (p != 0)
keif (p)
yang merupakan idiom umum di C dan C ++, meskipun Anda harus keluar dari kebiasaan jika Anda mengambil Java.0xDEADBEEF
.Jawaban:
2 poin:
hanya nilai konstan 0 dalam kode sumber yang merupakan pointer nol - implementasi compiler dapat menggunakan nilai apa pun yang diinginkan atau dibutuhkan dalam kode yang sedang berjalan. Beberapa platform memiliki nilai penunjuk khusus yang 'tidak valid' yang mungkin digunakan implementasi sebagai penunjuk null. C FAQ memiliki pertanyaan, "Serius, apakah mesin sebenarnya benar-benar menggunakan penunjuk nol bukan nol, atau representasi berbeda untuk penunjuk ke jenis yang berbeda?" , yang menunjukkan beberapa platform yang menggunakan properti 0 ini sebagai pointer nol di sumber C sementara direpresentasikan secara berbeda pada waktu proses. Standar C ++ memiliki catatan yang menjelaskan bahwa mengubah "ekspresi konstan integral dengan nilai nol selalu menghasilkan pointer nol,
nilai negatif mungkin dapat digunakan oleh platform sebagai alamat - standar C hanya harus memilih sesuatu untuk digunakan untuk menunjukkan pointer nol, dan nol dipilih. Sejujurnya saya tidak yakin apakah nilai sentinel lain juga dipertimbangkan.
Satu-satunya persyaratan untuk pointer nol adalah:
sumber
Secara historis, ruang alamat mulai dari 0 selalu ROM, digunakan untuk beberapa sistem operasi atau rutinitas penanganan interupsi tingkat rendah, saat ini, karena semuanya virtual (termasuk ruang alamat), sistem operasi dapat memetakan alokasi apa pun ke alamat mana pun, sehingga dapat secara khusus TIDAK mengalokasikan apa pun di alamat 0.
sumber
IIRC, nilai "pointer null" tidak dijamin nol. Kompilator menerjemahkan 0 ke dalam nilai "nol" apa pun yang sesuai untuk sistem (yang dalam praktiknya mungkin selalu nol, tetapi tidak harus). Terjemahan yang sama diterapkan setiap kali Anda membandingkan penunjuk dengan nol. Karena Anda hanya dapat membandingkan pointer satu sama lain dan terhadap nilai khusus-0 ini, ini mengisolasi programmer dari mengetahui apa pun tentang representasi memori sistem. Adapun mengapa mereka memilih 0 daripada 42 atau semacamnya, saya akan menebak itu karena sebagian besar pemrogram mulai menghitung pada 0 :) (Juga, pada kebanyakan sistem 0 adalah alamat memori pertama dan mereka ingin itu nyaman, karena dalam terjemahan praktek seperti yang saya gambarkan jarang benar-benar terjadi; bahasa hanya mengizinkannya).
sumber
int* p = 0
) mungkin membuat pointer yang berisi nilai0xdeadbeef
atau nilai lain yang lebih disukai. 0 adalah penunjuk nol, tetapi penunjuk nol belum tentu penunjuk ke alamat nol. :)Anda pasti salah paham tentang arti nol konstan dalam konteks pointer.
Baik di C maupun di C ++ pointer tidak dapat "memiliki nilai nol". Pointer bukanlah objek aritmatika. Mereka tidak boleh memiliki nilai numerik seperti "nol" atau "negatif" atau apa pun yang bersifat seperti itu. Jadi pernyataan Anda tentang "pointer ... memiliki nilai nol" tidak masuk akal.
Dalam C & C ++ pointer dapat memiliki nilai null-pointer yang telah dipesan . Representasi sebenarnya dari nilai null-pointer tidak ada hubungannya dengan "nol". Ini benar-benar bisa apa saja yang sesuai untuk platform tertentu. Memang benar bahwa pada kebanyakan plaform nilai penunjuk-nol direpresentasikan secara fisik oleh nilai alamat nol yang sebenarnya. Namun, jika pada beberapa platform, alamat 0 sebenarnya digunakan untuk beberapa tujuan (yaitu Anda mungkin perlu membuat objek di alamat 0), nilai penunjuk-nol pada platform tersebut kemungkinan besar akan berbeda. Ini bisa secara fisik direpresentasikan sebagai
0xFFFFFFFF
nilai alamat atau sebagai0xBAADBAAD
nilai alamat, misalnya.Namun demikian, terlepas dari bagaimana nilai penunjuk-nol direpresentasikan pada platform tertentu, dalam kode Anda, Anda masih akan terus menunjuk penunjuk-nol secara konstan
0
. Untuk menetapkan nilai null-pointer ke pointer tertentu, Anda akan terus menggunakan ekspresi sepertip = 0
. Merupakan tanggung jawab penyusun untuk mewujudkan apa yang Anda inginkan dan menerjemahkannya ke dalam representasi nilai penunjuk-nol yang tepat, misalnya untuk menerjemahkannya ke dalam kode yang akan memasukkan nilai alamat0xFFFFFFFF
ke penunjukp
, misalnya.Singkatnya, fakta bahwa Anda menggunakan
0
kode sorce Anda untuk menghasilkan nilai penunjuk-nol tidak berarti bahwa nilai penunjuk-nol entah bagaimana terikat ke alamat0
. Yang0
Anda gunakan dalam kode sumber Anda hanyalah "gula sintaksis" yang sama sekali tidak ada hubungannya dengan alamat fisik aktual yang menjadi nilai penunjuk-null "menunjuk".sumber
(p1 - nullptr) - (p2 - nullptr) == (p1 - p2)
.NULL
secara eksplisit tidak perlu diwakili oleh 0.Pada beberapa / banyak / semua sistem operasi, alamat memori 0 khusus dalam beberapa hal. Misalnya, sering dipetakan ke memori tidak valid / tidak ada, yang menyebabkan pengecualian jika Anda mencoba mengaksesnya.
Saya pikir nilai pointer biasanya diperlakukan sebagai angka unsigned: jika tidak misalnya pointer 32-bit hanya akan mampu mengatasi 2 GB memori, bukan 4 GB.
sumber
Dugaan saya adalah bahwa nilai ajaib 0 dipilih untuk menentukan penunjuk yang tidak valid karena dapat diuji dengan instruksi yang lebih sedikit. Beberapa bahasa mesin secara otomatis menyetel tanda nol dan tanda sesuai dengan data saat memuat register sehingga Anda dapat menguji penunjuk null dengan memuat instruksi kemudian dan cabang sederhana tanpa melakukan instruksi perbandingan terpisah.
(Kebanyakan ISA hanya menyetel flag pada instruksi ALU, bukan memuat. Dan biasanya Anda tidak menghasilkan pointer melalui komputasi, kecuali pada compiler saat mengurai sumber C. Tetapi setidaknya Anda tidak memerlukan konstanta lebar pointer yang berubah-ubah untuk bandingkan dengan.)
Di Commodore Pet, Vic20, dan C64 yang merupakan mesin pertama yang saya kerjakan, RAM dimulai di lokasi 0 sehingga benar-benar valid untuk membaca dan menulis menggunakan penunjuk nol jika Anda benar-benar menginginkannya.
sumber
Saya pikir itu hanya konvensi. Harus ada beberapa nilai untuk menandai penunjuk yang tidak valid.
Anda baru saja kehilangan satu byte ruang alamat, yang seharusnya jarang menjadi masalah.
Tidak ada petunjuk negatif. Pointer selalu tidak ditandatangani. Juga jika mereka bisa negatif, konvensi Anda berarti Anda kehilangan setengah ruang alamat.
sumber
char *p = (char *)1; --p;
. Karena perilaku pada penunjuk nol tidak ditentukan oleh standar, sistem inip
sebenarnya dapat membaca dan menulis alamat 0, kenaikan untuk memberikan alamat1
, dll.char x = ((char*)0);
membaca alamat nol dan menyimpan nilai itu ke dalam x. Kode tersebut akan menghasilkan Perilaku Tidak Terdefinisi pada implementasi apa pun yang tidak menentukan perilakunya, tetapi fakta bahwa standar mengatakan sesuatu adalah Perilaku Tidak Terdefinisi sama sekali tidak melarang implementasi menawarkan spesifikasi mereka sendiri untuk apa yang akan dilakukannya.*(char *)0
. Itu benar, tetapi dalam saran saya, penerapannya tidak perlu mendefinisikan perilaku*(char *)0
atau operasi penunjuk null lainnya.char *p = (char*)1; --p;
hanya akan ditentukan oleh standar jika urutan itu telah dilakukan setelah penunjuk ke sesuatu selain byte pertama dari suatu objek telah dilemparkan ke sebuahintptr_t
, dan hasil dari cor itu kebetulan menghasilkan nilai 1 , dan dalam kasus tertentu hasil dari--p
akan menghasilkan pointer ke byte sebelum nilai pointer, ketika dilemparkan keintptr_t
, telah menghasilkan1
.Meskipun C menggunakan 0 untuk merepresentasikan pointer nol, perlu diingat bahwa nilai dari pointer itu sendiri tidak boleh nol. Namun, sebagian besar pemrogram hanya akan menggunakan sistem di mana penunjuk nol sebenarnya adalah 0.
Tapi kenapa nol? Ya, itu satu alamat yang dibagikan setiap sistem. Dan seringkali alamat rendah dicadangkan untuk tujuan sistem operasi sehingga nilainya bekerja dengan baik sebagai terlarang untuk program aplikasi. Penetapan nilai integer yang tidak disengaja ke pointer cenderung berakhir nol seperti yang lainnya.
sumber
Secara historis, memori yang rendah dari suatu aplikasi ditempati oleh sumber daya sistem. Pada masa itulah nol menjadi nilai nol default.
Meskipun ini belum tentu benar untuk sistem modern, itu masih merupakan ide yang buruk untuk menetapkan nilai pointer ke apa pun selain alokasi memori apa yang telah diberikan kepada Anda.
sumber
Mengenai argumen tentang tidak menyetel pointer ke nol setelah menghapusnya sehingga di masa mendatang menghapus "mengekspos kesalahan" ...
Jika Anda benar-benar khawatir tentang hal ini maka pendekatan yang lebih baik, yang dijamin akan berhasil, adalah dengan memanfaatkan assert ():
Ini membutuhkan beberapa pengetikan ekstra, dan satu pemeriksaan ekstra selama debug build, tetapi pasti akan memberi Anda apa yang Anda inginkan: pemberitahuan ketika ptr dihapus 'dua kali'. Alternatif yang diberikan dalam diskusi komentar, tidak menyetel pointer ke null sehingga Anda akan mengalami crash, tidak dijamin akan berhasil. Lebih buruk lagi, tidak seperti di atas, ini dapat menyebabkan crash (atau lebih buruk lagi!) Pada pengguna jika salah satu "bug" ini berhasil masuk ke rak. Terakhir, versi ini memungkinkan Anda terus menjalankan program untuk melihat apa yang sebenarnya terjadi.
Saya menyadari ini tidak menjawab pertanyaan yang diajukan, tetapi saya khawatir seseorang yang membaca komentar mungkin sampai pada kesimpulan bahwa itu dianggap 'praktik yang baik' untuk TIDAK menetapkan petunjuk ke 0 jika mungkin mereka dikirim secara gratis () atau hapus dua kali. Dalam beberapa kasus, jika memungkinkan, JANGAN PERNAH menggunakan praktik yang baik untuk menggunakan Perilaku Tidak Terdefinisi sebagai alat debugging. Tidak seorang pun yang harus memburu bug yang pada akhirnya disebabkan oleh penghapusan penunjuk yang tidak valid akan mengusulkan hal ini. Jenis kesalahan ini membutuhkan waktu berjam-jam untuk memburu dan hampir selalu mempengaruhi program dengan cara yang sama sekali tidak terduga yang sulit untuk tidak mungkin untuk melacak kembali ke masalah aslinya.
sumber
Alasan penting mengapa banyak sistem operasi menggunakan semua-bit-nol untuk representasi penunjuk nol, adalah bahwa ini berarti
memset(struct_with_pointers, 0, sizeof struct_with_pointers)
dan yang serupa akan mengatur semua penunjuk di dalamstruct_with_pointers
ke penunjuk nol. Ini tidak dijamin oleh standar C, tetapi banyak program yang mengasumsikannya.sumber
Di salah satu mesin DEC lama (menurut saya PDP-8), runtime C akan melindungi memori halaman pertama memori sehingga setiap upaya untuk mengakses memori di blok itu akan menyebabkan pengecualian untuk dimunculkan.
sumber
Pilihan nilai sentinel bersifat arbitrer, dan ini sebenarnya sedang ditangani oleh versi C ++ berikutnya (secara informal dikenal sebagai "C ++ 0x", kemungkinan besar akan dikenal di masa mendatang sebagai ISO C ++ 2011) dengan diperkenalkannya kata kunci -1 untuk beberapa nilai N. Dengan kata lain, alamat biasanya diperlakukan sebagai nilai unsigned. Jika nilai maksimum digunakan sebagai nilai sentinel, maka nilai itu harus bervariasi dari sistem ke sistem tergantung pada ukuran memori sedangkan 0 selalu merupakan alamat yang dapat diwakili. Ini juga digunakan untuk alasan historis, karena alamat memori 0 biasanya tidak dapat digunakan dalam program, dan saat ini sebagian besar OS memiliki bagian kernel yang dimuat ke halaman bawah memori, dan halaman semacam itu biasanya dilindungi sedemikian rupa sehingga jika disentuh (didereferensi) oleh program (simpan kernel) akan menyebabkan kesalahan.
nullptr
untuk mewakili pointer bernilai null. Dalam C ++, nilai 0 dapat digunakan sebagai ekspresi inisialisasi untuk POD apa pun dan untuk objek apa pun dengan konstruktor default, dan memiliki arti khusus untuk menetapkan nilai sentinel dalam kasus inisialisasi penunjuk. Adapun mengapa nilai negatif tidak dipilih, alamat biasanya berkisar dari 0 hingga 2 Nsumber
Itu harus memiliki nilai. Jelas Anda tidak ingin menginjak nilai-nilai yang mungkin secara sah ingin digunakan oleh pengguna. Saya akan berspekulasi bahwa karena runtime C menyediakan segmen BSS untuk data yang diinisialisasi nol, itu masuk akal untuk menafsirkan nol sebagai nilai penunjuk yang tidak diinisialisasi.
sumber
Jarang OS memungkinkan Anda untuk menulis ke alamat 0. Adalah umum untuk menyimpan hal-hal khusus OS di memori rendah; yaitu, IDT, tabel halaman, dll. (Tabel harus dalam RAM, dan lebih mudah untuk menempelkannya di bagian bawah daripada mencoba dan menentukan di mana bagian atas RAM.) Dan tidak ada OS yang waras akan membiarkan Anda mengedit tabel sistem mau tidak mau.
Hal ini mungkin tidak ada dalam pikiran K & R ketika mereka membuat C, tetapi (bersama dengan fakta bahwa 0 == null cukup mudah diingat) membuat 0 menjadi pilihan populer.
sumber
Nilai
0
adalah nilai khusus yang memiliki berbagai arti dalam ekspresi tertentu. Dalam kasus pointer, seperti yang telah ditunjukkan berkali-kali, ini mungkin digunakan karena pada saat itu cara yang paling nyaman untuk mengatakan "masukkan nilai sentinel default di sini". Sebagai ekspresi konstan, ini tidak memiliki arti yang sama dengan bitwise zero (yaitu, semua bit diatur ke nol) dalam konteks ekspresi pointer. Di C ++, ada beberapa tipe yang tidak memiliki representasi bitwise zeroNULL
seperti pointer member dan pointer to member function.Untungnya, C ++ 0x memiliki kata kunci baru untuk "ekspresi yang berarti pointer tidak valid diketahui bahwa tidak juga memetakan ke bitwise nol untuk ekspresi integral":
nullptr
. Meskipun ada beberapa sistem yang dapat Anda targetkan dengan C ++ yang memungkinkan dereferensi alamat 0 tanpa muntah, jadi berhati-hatilah programmer.sumber
Sudah ada banyak jawaban bagus di utas ini; mungkin ada banyak alasan berbeda untuk memilih nilai
0
untuk pointer nol, tetapi saya akan menambahkan dua lagi:sumber
Ini tergantung pada implementasi pointer di C / C ++. Tidak ada alasan khusus mengapa NULL setara dalam penugasan ke sebuah pointer.
sumber
Ada alasan historis untuk ini, tetapi ada juga alasan pengoptimalan untuk itu.
Biasanya OS menyediakan proses dengan halaman memori yang diinisialisasi ke 0. Jika program ingin menafsirkan bagian dari halaman memori itu sebagai penunjuk maka nilainya 0, jadi cukup mudah bagi program untuk menentukan bahwa penunjuk tersebut adalah tidak diinisialisasi. (ini tidak berfungsi dengan baik saat diterapkan ke halaman flash yang tidak diinisialisasi)
Alasan lain adalah bahwa pada banyak prosesor, sangat mudah untuk menguji kesetaraan nilai dengan 0. Terkadang perbandingan gratis dilakukan tanpa memerlukan instruksi tambahan, dan biasanya dapat dilakukan tanpa perlu memberikan nilai nol di register lain atau sebagai literal dalam aliran instruksi untuk dibandingkan.
Perbandingan murah untuk kebanyakan prosesor adalah yang bertanda kurang dari 0, dan sama dengan 0. (bertanda lebih besar dari 0 dan tidak sama dengan 0 disiratkan oleh keduanya)
Karena 1 nilai dari semua nilai yang mungkin perlu disimpan sebagai nilai buruk atau tidak diinisialisasi, maka Anda sebaiknya menjadikannya salah satu yang memiliki pengujian termurah untuk kesetaraan dengan nilai buruk. Ini juga berlaku untuk string karakter yang diakhiri '\ 0'.
Jika Anda mencoba menggunakan lebih besar atau kurang dari 0 untuk tujuan ini, rentang alamat Anda akan terpotong menjadi dua.
sumber
Konstan
0
digunakan sebagai penggantiNULL
karena C dibuat oleh beberapa triliunan manusia gua dari tahun lalu,NULL
,NIL
,ZIP
, atauNADDA
akan memiliki semua dibuat jauh lebih masuk akal daripada0
.Memang. Meskipun banyak sistem operasi yang melarang Anda memetakan apa pun di alamat nol, bahkan dalam ruang alamat virtual (orang menyadari C adalah bahasa yang tidak aman, dan mencerminkan bahwa bug dereferensi penunjuk nol sangat umum, memutuskan untuk "memperbaikinya" dengan tidak mengizinkan kode ruang pengguna untuk dipetakan ke halaman 0; Jadi, jika Anda memanggil panggilan balik tetapi penunjuk panggilan balik adalah NULL, Anda tidak akan mengeksekusi beberapa kode arbitrer).
Karena
0
digunakan sebagai perbandingan pointer akan diganti dengan beberapa nilai spesifik implementasi , yang merupakan nilai kembali malloc pada kegagalan malloc.Ini akan lebih membingungkan.
sumber
int
tidak hanya berukuran sama dengan penunjuk - dalam banyak konteks, sebuahint
dan penunjuk dapat digunakan secara bergantian. Jika sebuah rutin mengharapkan sebuah pointer dan satu dilewatkan dalam sebuah integer 57, rutin tersebut akan menggunakan alamat dengan pola bit yang sama dengan nomor 57. Pada mesin-mesin tersebut, pola bit untuk menunjukkan sebuah pointer null adalah 0, jadi meneruskan int 0 akan melewatkan pointer nol.( Harap Baca Paragraf Ini Sebelum Membaca Posting.Saya meminta siapa pun yang tertarik membaca posting ini harus mencoba membacanya dengan cermat, dan tentu saja jangan downvote sampai Anda memahaminya sepenuhnya, terima kasih. )
Sekarang menjadi wiki komunitas, dengan demikian jika seseorang tidak setuju dengan salah satu konsep, harap memodifikasinya, dengan penjelasan yang jelas dan terperinci tentang apa yang salah dan mengapa, dan jika mungkin kutip sumber atau berikan bukti yang dapat direproduksi.
Menjawab
Berikut adalah beberapa alasan lain yang mungkin menjadi faktor yang mendasari NULL == 0
if(!my_ptr)
daripadaif(my_ptr==NULL)
.Di Sini Saya Ingin Mengatakan Sepatah Kata Tentang Jawaban Lain
Bukan Karena Gula Sintaksis
Mengatakan bahwa NULL adalah nol karena gula sintaksis, tidak terlalu masuk akal, jika demikian mengapa tidak menggunakan indeks 0 dari sebuah array untuk menahan panjangnya?
Sebenarnya C adalah bahasa yang paling mirip dengan implementasi internal, apakah masuk akal untuk mengatakan bahwa C memilih nol hanya karena gula sintaksis? Mereka lebih suka memberikan kata kunci null (seperti yang dilakukan banyak bahasa lain) daripada memetakan nol ke NULL!
Karena saat ini mungkin hanya gula sintaksis, jelas bahwa maksud asli dari pengembang bahasa C bukanlah untuk gula sintaksis, seperti yang akan saya tunjukkan lebih lanjut.
1) Spesifikasi
Namun meskipun benar bahwa spesifikasi C berbicara dari konstanta 0 sebagai penunjuk nol (bagian 6.3.2.3), dan juga mendefinisikan NULL sebagai implementasi yang ditentukan (bagian 7.19 dalam spesifikasi C11, dan 7.17 dalam spesifikasi C99), Faktanya tetap bahwa dalam buku "The C Programming Language" yang ditulis oleh penemu C berikut ini dinyatakan dalam bagian 5.4:
Seperti yang dapat dilihat (dari kata-kata "alamat nol") setidaknya maksud asli dari penulis C adalah alamat nol, dan bukan nol konstan, selain itu tampak dari kutipan ini bahwa alasan mengapa spesifikasi berbicara dari konstanta nol mungkin tidak mengecualikan ekspresi yang mengevaluasi ke nol, tetapi menyertakan konstanta bilangan bulat nol menjadi satu-satunya konstanta bilangan bulat yang diizinkan untuk digunakan dalam konteks penunjuk tanpa casting.
2) Ringkasan
Meskipun spesifikasi tidak mengatakan secara eksplisit bahwa alamat nol dapat diperlakukan berbeda dari konstanta nol, ia tidak mengatakan bahwa tidak, dan faktanya ketika berurusan dengan konstanta penunjuk-nol itu tidak mengklaimnya sebagai implementasi yang didefinisikan seperti itu dilakukan oleh konstanta yang ditentukan NULL , alih-alih mengklaimnya sebagai nol, menunjukkan bahwa mungkin ada perbedaan antara konstanta nol dan alamat nol.
(Namun jika ini kasusnya saya hanya bertanya-tanya mengapa NULL adalah implementasi yang ditentukan, karena dalam kasus seperti itu NULL juga bisa menjadi nol konstan, karena kompiler tetap harus mengubah semua konstanta nol menjadi implementasi aktual yang ditentukan NULL?)
Namun saya tidak melihat ini dalam tindakan nyata, dan dalam platform umum alamat nol dan nol konstan diperlakukan sama, dan menampilkan pesan kesalahan yang sama.
Selain itu, faktanya adalah bahwa sistem operasi saat ini sebenarnya menyimpan seluruh halaman pertama (kisaran 0x0000 hingga 0xFFFF), hanya untuk mencegah akses ke alamat nol karena penunjuk C's NULL, (lihat http://en.wikipedia.org/wiki/ Zero_page , serta "Windows Via C / C ++ oleh Jeffrey Richter dan Christophe Nasarre (diterbitkan oleh Microsoft Press)").
Jadi saya akan meminta dari siapa pun yang mengaku benar-benar melihatnya beraksi, untuk menentukan platform, dan kompiler, dan kode persis yang sebenarnya dia lakukan, (meskipun karena definisi yang tidak jelas dalam spesifikasi [seperti yang telah saya tunjukkan] kompiler apa pun dan platform bebas untuk melakukan apapun yang dia inginkan).
Namun tampaknya penulis C tidak memikirkan hal ini, dan mereka berbicara tentang "alamat nol", dan bahwa "C menjamin bahwa itu tidak pernah menjadi alamat yang valid", serta "NULL hanyalah a mnemonic ", dengan jelas menunjukkan bahwa niat aslinya bukanlah untuk" gula sintaksis ".
Bukan Karena Sistem Operasi
Juga mengklaim bahwa sistem operasi menolak akses ke alamat nol, karena beberapa alasan:
1) Ketika C ditulis tidak ada batasan seperti itu, seperti yang bisa dilihat di wikipage ini http://en.wikipedia.org/wiki/Zero_page .
2) Faktanya adalah bahwa kompiler C tidak mengakses alamat memori nol.
Ini tampaknya fakta dari makalah berikut oleh BellLabs ( http://www.cs.bell-labs.com/who/dmr/primevalC.html )
(Faktanya pada hari ini (seperti yang saya kutip referensi di atas dari wikipedia dan microsoft press), alasan untuk membatasi akses ke alamat nol adalah karena petunjuk C's NULL! Jadi pada akhirnya ternyata sebaliknya!)
3) Ingatlah bahwa C juga digunakan untuk menulis sistem operasi, dan bahkan C compiler!
Faktanya C dikembangkan untuk tujuan menulis sistem operasi UNIX dengannya, dan karena itu tampaknya tidak ada alasan mengapa mereka harus membatasi diri dari alamat nol.
(Hardware) Penjelasan Tentang Bagaimana Komputer (Secara Fisik) Mampu Mengakses Alamat Nol
Ada hal lain yang ingin saya jelaskan di sini, bagaimana mungkin merujuk alamat nol sama sekali?
Pikirkan sejenak, alamat diambil oleh prosesor, dan kemudian dikirim sebagai tegangan pada bus memori, yang kemudian digunakan oleh sistem memori untuk sampai ke alamat sebenarnya, namun alamat nol berarti tidak ada tegangan. , jadi bagaimana perangkat keras fisik dari sistem memori mengakses alamat nol?
Jawabannya adalah, bahwa alamat nol adalah default, dan dengan kata lain alamat nol selalu dapat diakses oleh sistem memori ketika bus memori benar-benar mati, dan dengan demikian setiap permintaan untuk membaca atau menulis tanpa menentukan alamat sebenarnya (yang mana adalah kasus dengan alamat nol) secara otomatis mengakses alamat nol.
sumber