C'de, sıfırın çeşitli değerleri arasında farklılıklar var gibi görünmektedir -- NULL
, NUL
ve 0
.
ASCII karakteri '0'
ın 48
veya 0x30
olarak değerlendirildiğini biliyorum.
NULL` işaretçisi genellikle şu şekilde tanımlanır:
#define NULL 0
Ya da
#define NULL (void *)0
Ek olarak, NUL
karakteri '\0'
da 0
olarak değerlendiriliyor gibi görünmektedir.
Bu üç değerin eşit olamayacağı zamanlar var mıdır?
Bu 64 bit sistemler için de geçerli mi?
Not: Bu cevap C++ için değil, C dili için geçerlidir.
0tamsayı sabitinin kullanıldığı bağlama göre farklı anlamları vardır. Her durumda, hala
0` değerine sahip bir tamsayı sabitidir, sadece farklı şekillerde tanımlanır.
Eğer bir işaretçi 0
sabit değişmezi ile karşılaştırılıyorsa, bu işaretçinin null işaretçi olup olmadığını kontrol eder. Bu 0
daha sonra null pointer sabiti olarak adlandırılır. C standardı, void *
türüne atanan 0
ın hem bir null gösterici hem de bir null gösterici sabiti olduğunu tanımlar.
Ayrıca, okunabilirliğe yardımcı olmak için stddef.h
başlık dosyasında NULL
makrosu sağlanmıştır. Derleyicinize bağlı olarak, #undef NULL
ve onu tuhaf bir şekilde yeniden tanımlamak mümkün olabilir.
Bu nedenle, null işaretçiyi kontrol etmenin bazı geçerli yolları aşağıda verilmiştir:
if (pointer == NULL)
NULLbir null işaretçisine eşit karşılaştırma yapmak için tanımlanmıştır. Geçerli bir null pointer sabiti olduğu sürece,
NULL`un gerçek tanımının ne olduğu uygulama tarafından tanımlanır.
if (pointer == 0)
0`, null pointer sabitinin başka bir temsilidir.
if (!pointer)
Bu `if' ifadesi "is not 0" ifadesini dolaylı olarak kontrol eder, bu nedenle "is 0" ifadesini tersine çeviririz.
Aşağıdakiler bir null işaretçiyi kontrol etmenin GEÇERSİZ yollarıdır:
int mynull = 0;
<some code>
if (pointer == mynull)
Derleyici için bu bir null işaretçi kontrolü değil, iki değişken üzerinde bir eşitlik kontrolüdür. mynull kodda hiç değişmezse ve derleyici optimizasyonları 0'ı if deyimine sabit olarak katlarsa bu belki işe yarayabilir, ancak bu garanti edilmez ve derleyicinin C Standardına göre en az bir tanılama mesajı (uyarı veya hata) üretmesi gerekir.
C dilinde null pointer'ın ne olduğuna dikkat edin. Altta yatan mimaride önemli değildir. Eğer temel mimaride 0xDEADBEEF adresi olarak tanımlanmış bir null pointer değeri varsa, bu karışıklığı çözmek derleyiciye kalmıştır.
Bu nedenle, bu komik mimaride bile, aşağıdaki yollar bir null işaretçiyi kontrol etmek için hala geçerli yollardır:
if (!pointer)
if (pointer == NULL)
if (pointer == 0)
Aşağıdakiler bir null işaretçiyi kontrol etmenin GEÇERSİZ yollarıdır:
#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)
çünkü bunlar derleyici tarafından normal karşılaştırmalar olarak görülür.
''\0'` boş bir karakter olarak tanımlanır - yani tüm bitleri sıfıra ayarlanmış bir karakter. Bunun işaretçilerle hiçbir ilgisi yoktur. Ancak bu koda benzer bir şey görebilirsiniz:
if (!*string_pointer)
dize işaretçisinin boş bir karakteri gösterip göstermediğini kontrol eder
if (*string_pointer)
dize işaretçisinin boş olmayan bir karakteri gösterip göstermediğini kontrol eder
Bunları null işaretçiler ile karıştırmayın. Sadece bit gösterimi aynı olduğu için ve bu bazı uygun çapraz durumlara izin verdiği için, gerçekten aynı şey değildirler.
Ayrıca, '\0'
(tüm karakter değişmezleri gibi) bu durumda sıfır değerine sahip bir tamsayı sabitidir. Yani '\0'
, süslenmemiş bir 0
tamsayı sabitine tamamen eşdeğerdir - tek fark, bir insan okuyucuya ilettiği niyettir ("Bunu boş karakter olarak kullanıyorum.").
Daha fazla bilgi için comp.lang.c SSS Soru 5.3 adresine bakın. C standardı için bu pdf adresine bakınız. Bölüm 6.3.2.3 İşaretçiler, paragraf 3'e göz atın.
NUL" 0 değil, ASCII NUL karakterini ifade eder. En azından ben bu şekilde kullanıldığını gördüm. Null pointer genellikle 0 olarak tanımlanır, ancak bu çalıştığınız ortama ve kullandığınız işletim sistemi veya dilin özelliklerine bağlıdır.
ANSI C'de null işaretçisi 0 tamsayı değeri olarak belirtilir. Dolayısıyla, bunun doğru olmadığı herhangi bir dünya ANSI C uyumlu değildir.
NULLun 0 olması garanti edilmez -- tam değeri mimariye bağlıdır. Çoğu büyük mimari bunu
(void*)0` olarak tanımlar.
''\0'` her zaman 0'a eşit olacaktır, çünkü 0 baytı bir karakter değişmezinde bu şekilde kodlanır.
C derleyicilerinin ASCII kullanması gerekip gerekmediğini hatırlamıyorum - eğer gerekmiyorsa, '0'
her zaman 48'e eşit olmayabilir. Ne olursa olsun, çok belirsiz sistemler üzerinde çalışmadığınız sürece EBCDIC gibi alternatif bir karakter seti kullanan bir sistemle karşılaşmanız pek olası değildir.
Çeşitli tiplerin boyutları 64 bit sistemlerde farklı olacaktır, ancak tamsayı değerleri aynı olacaktır.
Bazı yorumcular NULL'un 0'a eşit olması, ancak sıfır olmaması konusunda şüphelerini dile getirmişlerdir. İşte böyle bir sistemde beklenen çıktı ile birlikte örnek bir program:
#include <stdio.h>
int main () {
size_t ii;
int *ptr = NULL;
unsigned long *null_value = (unsigned long *)&ptr;
if (NULL == 0) {
printf ("NULL == 0\n"); }
printf ("NULL = 0x");
for (ii = 0; ii < sizeof (ptr); ii++) {
printf ("%02X", null_value[ii]); }
printf ("\n");
return 0;
}
O program yazdırabilir:
NULL == 0
NULL = 0x00000001