Di C, tampaknya ada perbedaan antara berbagai nilai nol - NULL
, NUL
dan 0
.
Saya tahu bahwa karakter ASCII '0'
mengevaluasi ke 48
atau 0x30
.
The NULL
pointer biasanya didefinisikan sebagai:
#define NULL 0
Atau
#define NULL (void *)0
Selain itu, ada NUL
karakter '\0'
yang tampaknya juga mengevaluasi 0
.
Apakah ada kalanya ketiga nilai ini tidak bisa sama?
Apakah ini juga berlaku pada sistem 64 bit?
NUL
tidak ada dalam bahasa atau perpustakaan standar C (atau dalam C ++ sejauh yang saya tahu). Karakter nol kadang-kadang disebut NUL, tetapi C atau C ++ biasanya disebut sebagai'\0'
.Jawaban:
Catatan: Jawaban ini berlaku untuk bahasa C, bukan C ++.
Null Pointers
Konstanta bilangan bulat konstan
0
memiliki arti yang berbeda tergantung pada konteks di mana ia digunakan. Dalam semua kasus, ini masih merupakan konstanta integer dengan nilai0
, itu hanya dijelaskan dengan cara yang berbeda.Jika sebuah pointer dibandingkan dengan konstanta literal
0
, maka ini adalah pemeriksaan untuk melihat apakah pointer tersebut adalah null pointer. Ini0
kemudian disebut sebagai konstanta penunjuk nol. Standar C mendefinisikan yang0
dilemparkan ke tipevoid *
adalah pointer nol dan konstanta pointer nol.Selain itu, untuk membantu keterbacaan, makro
NULL
disediakan di file headerstddef.h
. Bergantung pada kompiler Anda, dimungkinkan untuk#undef NULL
mendefinisikannya menjadi sesuatu yang aneh.Oleh karena itu, berikut adalah beberapa cara yang valid untuk memeriksa pointer nol:
NULL
didefinisikan untuk membandingkan sama dengan pointer nol. Ini adalah implementasi yang didefinisikan apa definisi sebenarnyaNULL
, selama itu adalah konstanta penunjuk nol yang valid.0
adalah representasi lain dari konstanta penunjuk nol.if
Pernyataan ini secara implisit memeriksa "bukan 0", jadi kami membalikkan artinya "adalah 0".Berikut ini adalah cara-cara INVALID untuk memeriksa pointer nol:
Untuk kompiler ini bukan pemeriksaan untuk pointer nol, tetapi pemeriksaan kesetaraan pada dua variabel. Ini mungkin bekerja jika mynull tidak pernah mengubah kode dan konstanta optimisasi kompiler melipat 0 ke dalam pernyataan if, tetapi ini tidak dijamin dan kompiler harus menghasilkan setidaknya satu pesan diagnostik (peringatan atau kesalahan) sesuai dengan Standar C.
Perhatikan bahwa apa yang dimaksud dengan pointer nol dalam bahasa C. Tidak masalah pada arsitektur yang mendasarinya. Jika arsitektur yang mendasari memiliki nilai pointer nol yang didefinisikan sebagai alamat 0xDEADBEEF, maka terserah kompiler untuk menyelesaikan masalah ini.
Karena itu, bahkan pada arsitektur lucu ini, cara-cara berikut masih merupakan cara yang valid untuk memeriksa null pointer:
Berikut ini adalah cara-cara INVALID untuk memeriksa pointer nol:
karena ini dilihat oleh kompiler sebagai perbandingan normal.
Karakter kosong
'\0'
didefinisikan sebagai karakter nol - yaitu karakter dengan semua bit diatur ke nol. Ini tidak ada hubungannya dengan pointer. Namun Anda mungkin melihat sesuatu yang mirip dengan kode ini:memeriksa apakah penunjuk string menunjuk pada karakter nol
memeriksa apakah penunjuk string menunjuk pada karakter yang bukan nol
Jangan bingung dengan pointer nol. Hanya karena representasi bitnya sama, dan ini memungkinkan beberapa kasus cross over yang nyaman, mereka sebenarnya tidak sama.
Selain itu,
'\0'
adalah (seperti semua literal karakter) konstanta integer, dalam hal ini dengan nilai nol. Jadi'\0'
benar-benar setara dengan0
konstanta bilangan bulat tanpa hiasan - satu-satunya perbedaan adalah niat yang disampaikan kepada pembaca manusia ("Saya menggunakan ini sebagai karakter nol.").Referensi
Lihat Pertanyaan 5.3 dari FAQ comp.lang.c untuk informasi lebih lanjut. Lihat pdf ini untuk standar C. Lihat bagian 6.3.2.3 Petunjuk, paragraf 3.
sumber
ptr
dengan semua-bit-nol . Ini bukanmemcmp
, tapi ini perbandingan menggunakan operator builtin. Satu sisi adalah konstanta pointer nol'\0'
, dan sisi lainnya adalah pointer. Selain dengan dua versi lainnya denganNULL
dan0
. Ketiganya melakukan hal yang sama.0xDEADBEEF
masih null pointer, tidak peduli apa suka penampilan bitstring, dan masih akan membandingkan sama denganNULL
,0
,\0
dan segala bentuk konstan nol pointer lainnya.ptr == '\0'
.Tampaknya sejumlah orang salah paham apa perbedaan antara NULL, '\ 0' dan 0. Jadi, untuk menjelaskan, dan dalam upaya untuk menghindari mengulangi hal-hal yang dikatakan sebelumnya:
Ekspresi konstan dari tipe
int
dengan nilai 0, atau ekspresi dari tipe ini, dilemparkan ke tipevoid *
adalah konstanta penunjuk nol , yang jika dikonversi ke sebuah penunjuk menjadi penunjuk nol . Dijamin oleh standar untuk membandingkan tidak sama dengan setiap pointer ke objek atau fungsi apa pun .NULL
adalah makro, didefinisikan sebagai konstanta penunjuk nol .\0
adalah konstruksi yang digunakan untuk mewakili karakter nol , digunakan untuk mengakhiri string.Sebuah karakter null adalah byte yang memiliki semua set ke 0 bit nya.
sumber
Ketiganya mendefinisikan arti nol dalam konteks yang berbeda.
Ketiganya selalu berbeda ketika Anda melihat memori:
Saya harap ini menjelaskannya.
sumber
sizeof('\0')
dan kaget.Jika NULL dan 0 sama dengan konstanta penunjuk nol, yang mana yang harus saya gunakan? di daftar FAQ C mengatasi masalah ini juga:
sumber
"karakter nol (NUL)" paling mudah dikesampingkan.
'\0'
adalah karakter literal. Di C, diimplementasikan sebagaiint
, jadi, sama dengan 0, yang dariINT_TYPE_SIZE
. Dalam C ++, karakter literal diimplementasikan sebagaichar
, yaitu 1 byte. Ini biasanya berbeda dariNULL
atau0
.Lanjut,
NULL
adalah nilai penunjuk yang menentukan bahwa suatu variabel tidak menunjuk ke ruang alamat apa pun. Mengesampingkan fakta bahwa biasanya diimplementasikan sebagai nol, itu harus mampu mengekspresikan ruang alamat lengkap arsitektur. Dengan demikian, pada arsitektur 32-bit NULL (kemungkinan) adalah 4-byte dan pada arsitektur 64-bit 8-byte. Ini terserah implementasi C.Akhirnya, literal
0
adalah tipeint
, yang berukuranINT_TYPE_SIZE
. Nilai default dariINT_TYPE_SIZE
dapat berbeda tergantung pada arsitektur.Apple menulis:
Wikipedia 64-bit :
Sunting : Menambahkan lebih banyak pada karakter literal.
Kode di atas mengembalikan 4 pada gcc dan 1 pada g ++.
sumber
'\0'
ini bukan nilai 1-byte. Ini adalah karakter literal, yang merupakan ekspresi konstanta bilangan bulat - jadi jika dapat dikatakan memiliki ukuran maka ukurannya adalahint
(yang harus setidaknya 2 byte). Jika Anda tidak percaya kepada saya, evaluasisizeof('\0')
dan lihat sendiri.'\0'
,0
dan0x0
semuanya sepenuhnya sama.sizeof('\0')
menggunakan kompiler C ++.Satu-L NUL, itu mengakhiri string.
NULL dua-L menunjuk ke hal yang tidak ada.
Dan aku akan bertaruh banteng emas
Bahwa tidak ada NULLL tiga-L.
Bagaimana Anda menangani NUL?
sumber
Sepotong bagus yang membantu saya ketika memulai dengan C (Diambil dari Pemrograman C Ahli oleh Linden)
The One 'l' nul dan The Two 'l' null
Hafalkan sajak kecil ini untuk mengingat terminologi yang benar untuk pointer dan ASCII nol:
Karakter ASCII dengan pola bit nol disebut "NUL". Nilai penunjuk khusus yang berarti titik penunjuk di mana-mana adalah "NULL". Kedua istilah itu tidak saling berarti.
sumber
NUL
adalah kode kontrol sepertiBEL
,VT
,HT
,SOT
dll dan dengan demikian memiliki max. 3 karakter."NUL" bukan 0, tetapi mengacu pada karakter ASCII NUL. Setidaknya, begitulah cara saya melihatnya digunakan. Pointer nol sering didefinisikan sebagai 0, tetapi ini tergantung pada lingkungan tempat Anda menjalankannya, dan spesifikasi sistem operasi atau bahasa apa pun yang Anda gunakan.
Dalam ANSI C, penunjuk nol ditentukan sebagai nilai integer 0. Jadi dunia mana pun yang tidak benar tidak sesuai dengan ANSI C.
sumber
Byte dengan nilai
0x00
adalah, pada tabel ASCII, karakter khusus disebutNUL
atauNULL
. Dalam C, karena Anda tidak boleh menanamkan karakter kontrol dalam kode sumber Anda, ini diwakili dalam string C dengan 0 yang diloloskan, yaitu\0
,.Tapi NULL sejati bukan nilai. Itu adalah tidak adanya nilai. Untuk sebuah pointer, itu berarti pointer itu tidak ada hubungannya. Dalam database, itu berarti tidak ada nilai dalam bidang (yang tidak sama dengan mengatakan bidang kosong, 0, atau diisi dengan spasi).
Nilai aktual yang digunakan format sistem atau file basis data tertentu untuk mewakili
NULL
belum tentu0x00
.sumber
NULL
tidak dijamin menjadi 0 - nilai pastinya tergantung arsitektur. Sebagian besar arsitektur besar mendefinisikannya(void*)0
.'\0'
akan selalu sama dengan 0, karena itulah cara byte 0 dikodekan dalam karakter literal.Saya tidak ingat apakah kompiler C diharuskan menggunakan ASCII - jika tidak,
'0'
mungkin tidak selalu sama dengan 48. Terlepas dari itu, kemungkinan besar Anda tidak akan pernah menemukan sistem yang menggunakan set karakter alternatif seperti EBCDIC kecuali jika Anda bekerja dengan sangat sistem tidak jelas.Ukuran dari berbagai jenis akan berbeda pada sistem 64-bit, tetapi nilai integer akan sama.
Beberapa komentator telah menyatakan keraguan bahwa NULL sama dengan 0, tetapi tidak menjadi nol. Berikut adalah contoh program, bersama dengan output yang diharapkan pada sistem seperti itu:
Program itu dapat mencetak:
sumber
(void *) 0 adalah NULL, dan '\ 0' mewakili akhir dari string.
sumber