Dalam ulasan kode baru-baru ini, seorang kontributor mencoba untuk menegakkan bahwa semua NULL
pemeriksaan pada pointer dilakukan dengan cara berikut:
int * some_ptr;
// ...
if (some_ptr == NULL)
{
// Handle null-pointer error
}
else
{
// Proceed
}
dari pada
int * some_ptr;
// ...
if (some_ptr)
{
// Proceed
}
else
{
// Handle null-pointer error
}
Saya setuju bahwa caranya sedikit lebih jelas dalam arti bahwa itu secara eksplisit mengatakan "Pastikan pointer ini bukan NULL", tetapi saya akan membantahnya dengan mengatakan bahwa siapa pun yang bekerja pada kode ini akan memahami bahwa menggunakan variabel pointer dalam sebuah if
Pernyataan secara implisit memeriksa NULL
. Saya juga merasa metode kedua memiliki peluang lebih kecil untuk memperkenalkan bug sejenisnya:
if (some_ptr = NULL)
yang merupakan rasa sakit mutlak untuk menemukan dan men-debug.
Cara mana yang Anda sukai dan mengapa?
c++
c
if-statement
null
coding-style
Bryan Marble
sumber
sumber
Jawaban:
Dalam pengalaman saya, tes formulir
if (ptr)
atauif (!ptr)
lebih disukai. Mereka tidak bergantung pada definisi simbolNULL
. Mereka tidak mengekspos kesempatan untuk penugasan yang tidak disengaja itu. Dan mereka jelas dan ringkas.Sunting: Seperti yang ditunjukkan SoapBox dalam komentar, mereka kompatibel dengan kelas C ++ seperti
auto_ptr
itu adalah objek yang bertindak sebagai pointer dan yang menyediakan konversibool
untuk mengaktifkan idiom ini dengan tepat. Untuk objek-objek ini, perbandingan eksplisitNULL
harus memohon konversi ke pointer yang mungkin memiliki efek samping semantik lain atau lebih mahal daripada keberadaan sederhana memeriksa bahwabool
menyiratkan konversi.Saya memiliki preferensi untuk kode yang mengatakan apa artinya tanpa teks yang tidak dibutuhkan.
if (ptr != NULL)
memiliki arti yang samaif (ptr)
tetapi dengan biaya spesifisitas yang berlebihan. Hal logis berikutnya adalah menulisif ((ptr != NULL) == TRUE)
dan dengan cara itu ada kegilaan. Bahasa C jelas bahwa boolean diuji olehif
,while
atau sejenisnya memiliki arti spesifik dari nilai bukan nol adalah benar dan nol adalah salah. Redundansi tidak membuatnya lebih jelas.sumber
int y = *x; if (!x) {...}
mana pengoptimal diizinkan untuk alasan bahwa karena*x
akan ditentukan jikax
NULL, itu tidak boleh NULL dan karenanya!x
harus FALSE. Ungkapan!ptr
itu bukan perilaku yang tidak terdefinisi. Dalam contoh, jika tes dilakukan sebelum penggunaan*x
, maka pengoptimal akan salah untuk menghilangkan tes.if (foo)
cukup jelas. Gunakan.sumber
Saya akan mulai dengan ini: konsistensi adalah raja, keputusan itu kurang penting daripada konsistensi dalam basis kode Anda.
Dalam C ++
NULL didefinisikan sebagai 0 atau 0L dalam C ++.
Jika Anda sudah membaca Bahasa Pemrograman C ++ Bjarne Stroustrup menyarankan menggunakan
0
secara eksplisit untuk menghindariNULL
makro ketika melakukan tugas , saya tidak yakin apakah dia melakukan hal yang sama dengan perbandingan, sudah lama sejak saya membaca buku, saya pikir dia baru saja melakukannyaif(some_ptr)
tanpa perbandingan eksplisit tapi saya tidak jelas tentang itu.Alasan untuk ini adalah bahwa
NULL
makro itu menipu (karena hampir semua makro) itu sebenarnya0
literal, bukan tipe unik seperti namanya. Menghindari makro adalah salah satu pedoman umum dalam C ++. Di sisi lain,0
tampak seperti bilangan bulat dan tidak bila dibandingkan dengan atau ditugaskan ke pointer. Secara pribadi saya bisa memilih jalan yang lain, tetapi biasanya saya melewatkan perbandingan eksplisit (meskipun beberapa orang tidak suka ini yang mungkin mengapa Anda memiliki kontributor yang menyarankan perubahan).Terlepas dari perasaan pribadi ini sebagian besar merupakan pilihan yang paling tidak jahat karena tidak ada satu metode yang benar.
Ini jelas dan idiom yang umum dan saya lebih suka, tidak ada kesempatan untuk secara tidak sengaja memberikan nilai selama perbandingan dan itu terbaca dengan jelas:
Ini jelas jika Anda tahu itu
some_ptr
adalah tipe pointer, tetapi mungkin juga terlihat seperti perbandingan integer:Ini jelas, dalam kasus umum masuk akal ... Tapi ini abstraksi yang bocor,
NULL
sebenarnya0
harfiah dan akhirnya bisa disalahgunakan dengan mudah:C ++ 0x memiliki nullptr yang sekarang menjadi metode yang disukai karena eksplisit dan akurat, hanya berhati-hati tentang penugasan tak disengaja:
Sampai Anda dapat bermigrasi ke C ++ 0x saya berpendapat itu buang-buang waktu mengkhawatirkan metode mana yang Anda gunakan, mereka semua tidak cukup itulah sebabnya nullptr ditemukan (bersama dengan masalah pemrograman generik yang muncul dengan penerusan sempurna .) Yang paling penting adalah menjaga konsistensi.
Dalam C
C adalah binatang yang berbeda.
Dalam C NULL dapat didefinisikan sebagai 0 atau sebagai ((batal *) 0), C99 memungkinkan untuk implementasi konstanta penunjuk nol yang ditentukan. Jadi sebenarnya turun ke definisi implementasi NULL dan Anda harus memeriksanya di perpustakaan standar Anda.
Macro sangat umum dan secara umum mereka banyak digunakan untuk menebus kekurangan dalam dukungan pemrograman generik dalam bahasa dan hal-hal lain juga. Bahasanya jauh lebih sederhana dan lebih mengandalkan pre-processor.
Dari perspektif ini saya mungkin akan merekomendasikan menggunakan
NULL
definisi makro dalam C.sumber
0
di C ++, itu memiliki makna dalam C:(void *)0
.0
lebih disukaiNULL
di C ++, karena kesalahan tipe bisa menjadi PITA.NULL
tetap nol.#define NULL ((void *)0)
darilinux/stddef.h
NULL
harus nol.Saya menggunakan
if (ptr)
, tapi ini sama sekali tidak layak diperdebatkan.Saya suka cara saya karena ringkas, meskipun yang lain mengatakan
== NULL
membuatnya lebih mudah untuk dibaca dan lebih eksplisit. Saya melihat dari mana mereka berasal, saya hanya tidak setuju dengan hal-hal tambahan yang membuatnya lebih mudah. (Saya benci makro, jadi saya bias.) Terserah Anda.Saya tidak setuju dengan argumen Anda. Jika Anda tidak mendapatkan peringatan untuk penugasan dalam kondisi bersyarat, Anda perlu menaikkan level peringatan Anda. Sederhana seperti itu. (Dan untuk cinta semua yang baik, jangan mengalihkan mereka.)
Catatan di C ++ 0x, bisa kita lakukan
if (ptr == nullptr)
, yang bagi saya memang lebih bagus. (Sekali lagi, saya benci makro. Tapinullptr
itu bagus.) Namun, saya tetap melakukannyaif (ptr)
, hanya karena itulah yang biasa saya lakukan.sumber
Terus terang, saya tidak mengerti mengapa itu penting. Salah satunya cukup jelas dan siapa pun yang cukup berpengalaman dengan C atau C ++ harus memahami keduanya. Namun satu komentar:
Jika Anda berencana untuk mengenali kesalahan dan tidak melanjutkan menjalankan fungsi (yaitu, Anda akan melempar pengecualian atau mengembalikan kode kesalahan segera), Anda harus menjadikannya klausa penjaga:
Dengan cara ini, Anda menghindari "kode panah."
sumber
if(!p)
merupakan perilaku yang tidak terdefinisi. Itu bisa berhasil atau tidak.if(!p)
itu bukan perilaku yang tidak ditentukan, itu adalah baris sebelumnya. Danif(p==NULL)
akan memiliki masalah yang sama persis.Secara pribadi saya selalu menggunakan
if (ptr == NULL)
karena itu membuat maksud saya eksplisit, tetapi pada titik ini hanya kebiasaan.Penggunaan
=
di tempat==
akan ditangkap oleh kompiler yang kompeten dengan pengaturan peringatan yang benar.Poin penting adalah memilih gaya yang konsisten untuk grup Anda dan tetap menggunakannya. Tidak peduli ke arah mana Anda pergi, pada akhirnya Anda akan terbiasa, dan kehilangan gesekan saat bekerja dengan kode orang lain akan diterima.
sumber
Hanya satu poin lagi yang mendukung
foo == NULL
praktik ini: Jikafoo
adalah, katakanlah, satuint *
atau abool *
, makaif (foo)
cek tersebut dapat secara tidak sengaja ditafsirkan oleh pembaca sebagai pengujian nilai pointee, yaitu sebagaiif (*foo)
. TheNULL
perbandingan di sini adalah pengingat bahwa kita sedang berbicara tentang pointer.Tapi saya kira konvensi penamaan yang baik membuat argumen ini bisa diperdebatkan.
sumber
Sebenarnya, saya menggunakan kedua varian.
Ada situasi, di mana Anda pertama kali memeriksa validitas pointer, dan jika itu NULL, Anda cukup kembali / keluar dari suatu fungsi. (Saya tahu ini dapat mengarah pada diskusi "jika suatu fungsi hanya memiliki satu titik keluar")
Sebagian besar waktu, Anda memeriksa pointer, lalu melakukan apa yang Anda inginkan dan kemudian menyelesaikan kasus kesalahan. Hasilnya bisa berupa kode indentasi x-times jelek dengan multiple if's.
sumber
goto
mungkin sangat berguna. Juga dalam banyak kasusmalloc()
yang perlu dibersihkan bisa diganti dengan yang lebih cepatalloca()
. Saya tahu mereka tidak direkomendasikan, tetapi mereka ada karena suatu alasan (oleh saya, label dengan nama baikgoto
jauh lebih bersih daripadaif/else
pohon yang dikaburkan ).alloca
tidak standar dan sama sekali tidak aman. Jika gagal, program Anda akan meledak. Tidak ada peluang untuk pemulihan, dan karena tumpukan relatif kecil, kemungkinan besar kegagalan. Jika gagal, Anda mungkin menghadapi tumpukan dan memperkenalkan kerentanan yang membahayakan hak istimewa. Jangan pernah gunakanalloca
atau vlas kecuali Anda memiliki batasan kecil pada ukuran yang akan dialokasikan (dan kemudian Anda mungkin juga menggunakan array normal).Bahasa Pemrograman C (K&R) akan meminta Anda memeriksa null == ptr untuk menghindari tugas yang tidak disengaja.
sumber
if (!valid)
atasif (valid == 0
).Jika gaya dan format akan menjadi bagian dari ulasan Anda, harus ada panduan gaya yang disepakati untuk diukur. Jika ada, lakukan apa yang dikatakan panduan gaya. Jika tidak ada, detail seperti ini harus dibiarkan seperti yang tertulis. Ini buang-buang waktu dan energi, dan mengalihkan perhatian dari apa yang seharusnya diungkapkan oleh ulasan kode. Serius, tanpa panduan gaya saya akan mendorong untuk TIDAK mengubah kode seperti ini sebagai prinsip, bahkan ketika itu tidak menggunakan konvensi yang saya sukai.
Dan itu tidak penting, tetapi preferensi pribadi saya
if (ptr)
. Maknanya lebih langsung jelas bagi saya daripada bahkanif (ptr == NULL)
.Mungkin dia mencoba mengatakan bahwa lebih baik menangani kondisi kesalahan sebelum jalan bahagia? Dalam hal ini saya masih tidak setuju dengan pengulas. Saya tidak tahu bahwa ada konvensi yang diterima untuk ini, tetapi menurut saya kondisi yang paling "normal" harus didahulukan dalam pernyataan if. Dengan begitu saya semakin sedikit menggali untuk mengetahui apa fungsi semua ini dan bagaimana cara kerjanya.
Pengecualian untuk ini adalah jika kesalahan menyebabkan saya menyelamatkan dari fungsi, atau saya dapat memulihkannya sebelum pindah. Dalam kasus tersebut, saya menangani kesalahan terlebih dahulu:
Dengan menghadapi kondisi yang tidak biasa di depan, saya bisa mengurusnya dan kemudian melupakannya. Tetapi jika saya tidak bisa kembali ke jalan bahagia dengan memegangnya di depan, maka itu harus ditangani setelah kasus utama karena membuat kode lebih mudah dimengerti. Menurutku.
Tetapi jika itu tidak ada dalam panduan gaya maka itu hanya pendapat saya, dan pendapat Anda sama validnya. Baik terstandarisasi atau tidak. Jangan biarkan resensi pseudo-standar hanya karena dia punya pendapat.
sumber
Ini adalah salah satu dasar dari kedua bahasa yang pointer mengevaluasi untuk jenis dan nilai yang dapat digunakan sebagai ekspresi kontrol,
bool
dalam C ++ danint
dalam C. Cukup gunakan.sumber
if (foo = bar)
secara tidak sengaja.Karena itu saya lebih suka
atau
Namun, jika saya menulis seperangkat pedoman gaya saya tidak akan memasukkan hal-hal seperti ini di dalamnya, saya akan meletakkan hal-hal seperti:
sumber
Saya penggemar berat fakta bahwa C / C ++ tidak memeriksa jenis dalam kondisi boolean
if
,for
danwhile
pernyataan. Saya selalu menggunakan yang berikut ini:bahkan pada bilangan bulat atau tipe lain yang diubah menjadi bool:
Pengodean dalam gaya ini lebih mudah dibaca dan lebih jelas bagi saya. Hanya pendapat pribadi saya.
Baru-baru ini, ketika bekerja pada mikrokontroler OKI 431, saya perhatikan bahwa berikut ini:
lebih efisien daripada
karena dalam kasus selanjutnya kompiler harus membandingkan nilai chx ke 1. Di mana chx hanyalah flag true / false.
sumber
Sebagian besar kompiler yang saya gunakan setidaknya akan memperingatkan pada
if
tugas tanpa sintaks lebih lanjut, jadi saya tidak membeli argumen itu. Yang mengatakan, saya telah menggunakan keduanya secara profesional dan tidak memiliki preferensi untuk keduanya. Ini== NULL
jelas lebih jelas menurut saya.sumber