Apakah saya diizinkan menggunakan NULL
pointer sebagai pengganti nilai 0
?
Atau adakah yang salah dengan perbuatan itu?
Seperti, misalnya:
int i = NULL;
sebagai pengganti:
int i = 0;
Sebagai percobaan saya menyusun kode berikut:
#include <stdio.h>
int main(void)
{
int i = NULL;
printf("%d",i);
return 0;
}
Keluaran:
0
Memang itu memberi saya peringatan ini, yang sepenuhnya benar sendiri:
warning: initialization makes integer from pointer without a cast [-Wint-conversion]
tetapi hasilnya masih setara.
- Apakah saya beralih ke "Perilaku Tidak Terdefinisi" dengan ini?
- Apakah diizinkan menggunakan
NULL
cara ini? - Apakah ada yang salah dengan menggunakan
NULL
sebagai nilai numerik dalam ekspresi aritmatika? - Dan apa hasil dan perilaku di C ++ untuk kasus ini?
Saya telah membaca jawaban dari Apa perbedaan antara NULL, '\ 0' dan 0 tentang apa perbedaan antara NULL
, \0
dan 0
, tetapi saya tidak mendapatkan informasi yang ringkas dari sana, jika cukup diizinkan dan juga hak untuk digunakan NULL
sebagai nilai untuk beroperasi dengan dalam penugasan dan operasi aritmatika lainnya.
Jawaban:
Tidak , tidak aman untuk melakukannya.
NULL
adalah konstanta null-pointer, yang dapat memiliki tipeint
, tetapi yang lebih tipikal memiliki tipevoid *
(dalam C), atau sebaliknya tidak dapat langsung ditetapkan keint
(dalam C ++> = 11). Kedua bahasa memungkinkan pointer untuk dikonversi ke integer, tetapi mereka tidak menyediakan untuk konversi tersebut dilakukan secara implisit (meskipun beberapa kompiler menyatakan bahwa sebagai ekstensi). Selain itu, meskipun itu umum untuk mengkonversi pointer nol ke integer untuk menghasilkan nilai 0, standar tidak menjamin itu. Jika Anda menginginkan konstanta dengan tipeint
dan nilai 0 maka eja0
.Ya, pada implementasi mana pun yang
NULL
meluas ke nilai dengan tipevoid *
atau lainnya yang tidak dapat langsung ditentukanint
. Standar tidak menentukan perilaku penugasan Anda pada implementasi seperti itu, karena perilakunya tidak terdefinisi.Itu gaya yang buruk, dan itu akan merusak beberapa sistem dan dalam beberapa keadaan. Karena Anda tampaknya menggunakan GCC, itu akan pecah dalam contoh Anda sendiri jika Anda dikompilasi dengan
-Werror
opsi.Iya. Sama sekali tidak dijamin memiliki nilai numerik. Jika yang Anda maksud 0 maka tulis 0, yang tidak hanya didefinisikan dengan baik, tetapi lebih pendek dan lebih jelas.
Bahasa C ++ lebih ketat tentang konversi daripada C dan memiliki aturan yang berbeda untuk
NULL
, tetapi di sana juga, implementasi dapat menyediakan ekstensi. Sekali lagi, jika Anda berarti 0 maka itu yang harus Anda tulissumber
void *
" hanya benar dari C.void *
bukan tipe legal untuk C ++ (karena Anda tidak dapat menetapkanvoid*
untuk tipe pointer lainnya). Dalam C ++ 89 dan C ++ 03, sebenarnyaNULL
harus bertipeint
, tetapi dalam versi yang lebih baru bisa (dan biasanya)nullptr_t
.void*
keint
perilaku tidak terdefinisi. Bukan itu; itu adalah implementasi perilaku yang ditentukan.NULL
adalah beberapa konstanta null pointer. Dalam C itu bisa berupa ekspresi konstanta integer dengan nilai0
atau ekspresi seperti ituvoid*
, dengan yang terakhir lebih mungkin. Yang berarti Anda tidak dapat berasumsi untuk menggunakan secaraNULL
bergantian dengan nol. Misalnya, dalam contoh kode iniMengganti
0
denganNULL
tidak dijamin sebagai program C yang valid, karena penambahan antara dua pointer (apalagi dari jenis pointer yang berbeda) tidak ditentukan. Ini akan menyebabkan diagnostik dikeluarkan karena pelanggaran kendala. Operan untuk penambahan tidak akan valid .Adapun C ++, semuanya agak berbeda. Kurangnya konversi implisit dari
void*
ke jenis objek lain berarti yangNULL
secara historis didefinisikan0
dalam kode C ++. Di C ++ 03, Anda mungkin bisa lolos begitu saja. Tetapi karena C ++ 11 secara hukum dapat didefinisikan sebagainullptr
kata kunci . Sekarang lagi menghasilkan kesalahan, sejakstd::nullptr_t
mungkin tidak ditambahkan ke tipe pointer.Jika
NULL
ditentukan saatnullptr
itu, bahkan percobaan Anda menjadi tidak valid. Tidak ada konversi daristd::nullptr_t
ke integer. Itulah mengapa ini dianggap sebagai konstanta null pointer yang lebih aman.sumber
NULL
pada kedua bahasa.0
null pointer konstan: "jelas sebagai sop untuk semua kode C yang masih ada ditulis dengan buruk yang membuat asumsi yang salah"Aturan bervariasi antara bahasa dan versinya. Dalam beberapa kasus Anda bisa dan dalam kasus lain, Anda tidak bisa. Bagaimanapun, Anda seharusnya tidak . Jika Anda beruntung, kompiler Anda akan memperingatkan ketika Anda mencobanya atau bahkan lebih baik, gagal dikompilasi.
Dalam C ++, sebelum C ++ 11 (kutipan dari C ++ 03):
Tidak masuk akal untuk menggunakan konstanta penunjuk nol sebagai integer. Namun...
Jadi, itu akan berfungsi secara teknis bahkan jika itu tidak masuk akal. Karena teknis ini, Anda mungkin menemukan program yang ditulis dengan buruk yang menyalahgunakan
NULL
.Sejak C ++ 11 (kutipan dari konsep terbaru):
A
std::nullptr_t
tidak dapat dikonversi menjadi integer, jadi menggunakanNULL
integer hanya akan bekerja secara kondisional, tergantung pada pilihan yang dibuat oleh implementasi bahasa.PS
nullptr
adalah nilai jenisstd::nullptr_t
. Kecuali Anda membutuhkan program untuk mengkompilasi di pra-C ++ 11, Anda harus selalu menggunakannullptr
bukanNULL
.C sedikit berbeda (kutipan dari C11 draft N1548):
Jadi, kasusnya mirip dengan posting C ++ 11 yaitu penyalahgunaan
NULL
karya bersyarat tergantung pada pilihan yang dibuat oleh implementasi bahasa.sumber
Ya , meskipun tergantung pada pelaksanaan Anda mungkin perlu para pemain. Tapi ya, itu 100% sah, jika tidak.
Meskipun itu benar-benar gaya yang sangat buruk (tidak perlu dikatakan?).
NULL
adalah, atau dulu, sebenarnya bukan C ++, itu adalah C. Namun standar tidak , seperti untuk banyak warisan C, memiliki dua klausa ([diff.null] dan [support.types.nullptr]) yang secara teknis membuatNULL
C ++. Ini adalah konstanta null-pointer implementasi-didefinisikan . Oleh karena itu, bahkan jika itu gaya yang buruk, secara teknis C ++ seperti yang seharusnya.Seperti yang ditunjukkan dalam catatan kaki , implementasi yang mungkin bisa
0
atau0L
, tetapi tidak(void*)0
.NULL
bisa, tentu saja (standar tidak secara eksplisit mengatakannya, tetapi itu adalah satu-satunya pilihan yang tersisa setelah0
atau0L
) menjadinullptr
. Itu hampir tidak pernah terjadi, tetapi itu adalah kemungkinan yang sah.Peringatan bahwa kompiler menunjukkan kepada Anda menunjukkan bahwa kompiler sebenarnya tidak sesuai (kecuali Anda dikompilasi dalam mode C). Karena, well, menurut peringatan itu, ia benar - benar mengkonversi null pointer (bukan
nullptr
yang akan menjadinullptr_t
, yang akan berbeda), jadi tampaknya definisiNULL
memang(void*)0
, yang mungkin tidak.Either way, Anda memiliki dua kemungkinan kasus yang sah (mis. Kompiler tidak rusak). Entah (kasus realistis),
NULL
adalah sesuatu seperti0
atau0L
, maka Anda memiliki konversi "nol atau satu" menjadi bilangan bulat, dan Anda baik untuk melakukannya.Atau
NULL
memangnullptr
. Dalam hal ini Anda memiliki nilai berbeda yang memiliki jaminan tentang perbandingan serta konversi yang jelas dari bilangan bulat, tetapi sayangnya tidak untuk bilangan bulat. Namun, ia memiliki konversi yang jelas kebool
(menghasilkanfalse
), danbool
memiliki konversi yang jelas ke integer (menghasilkan0
).Sayangnya, itu adalah dua konversi, jadi itu tidak dalam "nol atau satu" seperti yang ditunjukkan dalam [konv]. Jadi, jika implementasi Anda didefinisikan
NULL
sebagainullptr
, maka Anda harus menambahkan pemeran eksplisit agar kode Anda benar.sumber
Dari faq C:
sumber
Penafian: Saya tidak tahu C ++. Jawaban saya tidak dimaksudkan untuk diterapkan dalam konteks C ++
'\0'
adalahint
dengan nilai nol, persis seperti 100%0
.Dalam konteks pointer ,
0
danNULL
setara 100%:semuanya setara 100%.
Perhatikan tentang
ptr + NULL
Konteks
ptr + NULL
ini bukan yang dari pointer. Tidak ada definisi untuk penambahan pointer dalam bahasa C; pointer dan integer dapat ditambahkan (atau dikurangkan). Dalamptr + NULL
jika salahptr
atauNULL
adalah pointer, yang lain harus integer, sehinggaptr + NULL
secara efektif(int)ptr + NULL
atauptr + (int)NULL
dan tergantung pada definisiptr
danNULL
beberapa perilaku dapat diharapkan: itu semua kerja, peringatan untuk konversi antara pointer dan integer, kegagalan untuk mengkompilasi, .. .sumber
#define NULL (void *)0
sebelumnya. Apakah Anda yakin NULL dan 0 polos 100% setara?ptr + NULL
tidak menggunakanNULL
dalam konteks pointernullptr
itu, tetapi((void*)0)
dan0
(atau'\0'
) setara dalam konteks petunjuk ...if (ptr == '\0' /* or equivalent 0, NULL */)
Tidak, tidak lagi disukai untuk menggunakan
NULL
(cara lama initilisasi pointer).Sejak C ++ 11:
Kata kunci
nullptr
menunjukkan pointer literal. Ini adalah nilai dari tipe std :: nullptr_t. Ada konversi implisit darinullptr
ke nilai pointer nol dari semua jenis pointer dan pointer ke tipe anggota. Konversi serupa ada untuk konstanta penunjuk nol, yang mencakup nilai tipestd::nullptr_t
serta makroNULL
.https://en.cppreference.com/w/cpp/language/nullptr
Sebenarnya, std :: nullptr_t adalah tipe dari null pointer literal
nullptr
,. Ini adalah tipe berbeda yang bukan tipe pointer atau pointer ke tipe anggota.Keluaran:
sumber