NULL, '\ 0' और 0 में क्या अंतर है?


309

- सी में, वहाँ शून्य के विभिन्न मूल्यों के बीच मतभेद होना दिखाई NULL, NULऔर 0

मुझे पता है कि ASCII चरित्र का '0'मूल्यांकन करता है 48या 0x30

NULLसूचक आमतौर पर के रूप में परिभाषित किया गया है:

#define NULL 0

या

#define NULL (void *)0

इसके अलावा, वहाँ NULचरित्र है '\0'जो के 0रूप में अच्छी तरह से मूल्यांकन करने के लिए लगता है ।

क्या ऐसे समय हैं जब ये तीन मूल्य समान नहीं हो सकते हैं?

क्या यह 64 बिट सिस्टम पर भी सच है?


1
0 और NULL के बीच अंतर के बारे में कुछ और जानकारी के लिए stackoverflow.com/questions/176989/… देखें ।
डेविड रॉड्रिग्ज - ड्रिबीज

7
पहचानकर्ता NULC मानक भाषा या लाइब्रेरी (या C ++ में जहाँ तक मुझे पता है) मौजूद नहीं है। अशक्त चरित्र को कभी-कभी NUL भी कहा जाता है, लेकिन यह C या C ++ है, जिसे आमतौर पर केवल के रूप में संदर्भित किया जाता है '\0'
कीथ थॉम्पसन

जवाबों:


351

नोट: यह उत्तर C भाषा पर लागू होता है, C ++ पर नहीं।


अशक्त संकेत

पूर्णांक स्थिरांक का शाब्दिक 0अर्थ उस संदर्भ के आधार पर अलग-अलग होता है जिसमें इसका उपयोग किया जाता है। सभी मामलों में, यह अभी भी मूल्य के साथ पूर्णांक स्थिर है 0, यह सिर्फ अलग-अलग तरीकों से वर्णित है।

यदि एक पॉइंटर को निरंतर शाब्दिक की तुलना में किया जा रहा है 0, तो यह देखने के लिए एक जांच है कि क्या सूचक एक अशक्त पॉइंटर है। यह 0तब एक अशक्त सूचक के रूप में संदर्भित किया जाता है। C मानक परिभाषित करता है कि 0टाइप करने के लिए डाली void *एक अशक्त सूचक और अशक्त सूचक स्थिरांक है।

इसके अतिरिक्त, पठनीयता में मदद करने के लिए, NULLहेडर फ़ाइल में मैक्रो प्रदान किया जाता है stddef.h। आपके संकलक के आधार पर यह संभव हो सकता है #undef NULLऔर इसे कुछ निराला करने के लिए फिर से परिभाषित कर सकता है ।

इसलिए, यहां एक शून्य सूचक की जांच करने के कुछ मान्य तरीके दिए गए हैं:

if (pointer == NULL)

NULLएक अशक्त सूचक के बराबर तुलना करने के लिए परिभाषित किया गया है। इसे लागू करना यह परिभाषित करता है कि वास्तविक परिभाषा क्या NULLहै, जब तक कि यह एक वैध नल सूचक स्थिरांक है।

if (pointer == 0)

0 अशक्त सूचक का एक और प्रतिनिधित्व है।

if (!pointer)

यह ifकथन स्पष्ट रूप से "0 नहीं है" की जाँच करता है, इसलिए हम इसका मतलब यह है कि "0 है"।

शून्य सूचक के लिए जाँच करने के लिए निम्न तरीके हैं:

int mynull = 0;
<some code>
if (pointer == mynull)

कंपाइलर के लिए यह अशक्त सूचक के लिए चेक नहीं है, लेकिन दो चर पर एक समानता की जांच है। यह काम कर सकता है यदि mynull कोड में कभी नहीं बदलता है और कंपाइलर ऑप्टिमाइज़ेशन निरंतर 0 को if स्टेटमेंट में फोल्ड करता है, लेकिन इसकी गारंटी नहीं है और कंपाइलर को C Standard के अनुसार कम से कम एक डायग्नोस्टिक मैसेज (चेतावनी या त्रुटि) का उत्पादन करना पड़ता है।

ध्यान दें कि सी भाषा में एक अशक्त सूचक क्या है। यह अंतर्निहित वास्तुकला पर कोई फर्क नहीं पड़ता। यदि अंतर्निहित आर्किटेक्चर में अशक्त सूचक मान 0xDEADBEEF के रूप में परिभाषित किया गया है, तो यह इस गड़बड़ को सुलझाने के लिए कंपाइलर पर निर्भर है।

इस तरह, इस अजीब वास्तुकला पर भी, निम्न तरीके अभी भी एक शून्य सूचक की जांच करने के वैध तरीके हैं:

if (!pointer)
if (pointer == NULL)
if (pointer == 0)

शून्य सूचक के लिए जाँच करने के लिए निम्न तरीके हैं:

#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)

क्योंकि ये एक कंपाइलर द्वारा सामान्य तुलना के रूप में देखे जाते हैं।

अशक्त वर्ण

'\0'को एक अशक्त चरित्र के रूप में परिभाषित किया गया है - यह एक ऐसा चरित्र है जिसमें सभी बिट्स शून्य पर सेट हैं। इसका संकेत देने वालों से कोई लेना-देना नहीं है। हालाँकि आप इस कोड के समान कुछ देख सकते हैं:

if (!*string_pointer)

जाँचता है कि स्ट्रिंग सूचक एक अशक्त चरित्र की ओर इशारा कर रहा है

if (*string_pointer)

जाँचता है कि स्ट्रिंग सूचक एक गैर-अशक्त चरित्र की ओर इशारा कर रहा है

इन अशक्त बिंदुओं के साथ भ्रमित मत हो। सिर्फ इसलिए कि बिट प्रतिनिधित्व समान है, और यह मामलों में कुछ सुविधाजनक क्रॉस के लिए अनुमति देता है, वे वास्तव में एक ही चीज नहीं हैं।

इसके अतिरिक्त, '\0'मान शून्य के साथ इस मामले में (सभी वर्ण शाब्दिक की तरह) एक पूर्णांक स्थिरांक है। तो '\0'पूरी तरह से एक अनियंत्रित 0पूर्णांक स्थिरांक के बराबर है - एकमात्र अंतर इस इरादे में है कि यह एक मानव पाठक ("मैं इसे एक अशक्त चरित्र के रूप में उपयोग कर रहा हूं") तक पहुंचाता हूं।

संदर्भ

अधिक के लिए comp.lang.c के प्रश्न 5.3 देखें । C मानक के लिए इस pdf को देखें । अनुभाग 6.3.2.3 अंक, पैराग्राफ 3 देखें।


3
एफएक्यू सूची की ओर इशारा करने के लिए धन्यवाद। हालाँकि, यह भी देखें c-faq.com/null/nullor0.html
सिनान

4
नहीं, आप की तुलना नहीं होगा ptrकरने के लिए सभी बिट्स-शून्य । यह एक नहीं है memcmp, लेकिन यह एक बिलिन ऑपरेटर के उपयोग से तुलना है। एक पक्ष एक नल सूचक स्थिर है '\0', और दूसरा पक्ष एक सूचक है। रूप में अच्छी तरह के साथ अन्य दो संस्करणों के साथ के रूप में NULLऔर 0। वे तीनों एक ही काम करते हैं।
जोहान्स स्काउब -

6
आप बिल्टिन तुलना ऑपरेटर को एक ऐसी चीज के रूप में ले रहे हैं जो बिट-स्ट्रिंग्स की तुलना करेगा। लेकिन ऐसा नहीं है। यह दो मूल्यों की तुलना करता है, जो अमूर्त अवधारणाएं हैं। एक अशक्त सूचक के रूप में है कि आंतरिक रूप से प्रतिनिधित्व किया है तो 0xDEADBEEFअभी भी एक नल पॉइंटर, कोई फर्क नहीं पड़ता अपने bitstring लगता है कि क्या है, और यह अभी भी करने के लिए बराबर की तुलना करेंगे NULL, 0, \0और अन्य सभी नल पॉइंटर निरंतर रूपों।
जोहान्स स्काउब -

2
आप तुलना ऑपरेटर के बारे में एक अच्छी बात करते हैं। मैंने C99 पर ब्रश किया। यह कहता है "मान 0 के साथ एक पूर्णांक स्थिर अभिव्यक्ति, या इस तरह की अभिव्यक्ति शून्य टाइप करने के लिए डाली जाती है, इसे एक शून्य सूचक स्थिरांक कहा जाता है।" यह भी कहता है कि एक चरित्र शाब्दिक पूर्णांक स्थिर अभिव्यक्ति है। इस प्रकार, सकर्मक संपत्ति के द्वारा आप सही हैं ptr == '\0'
एंड्रयू केटॉन

2
".... यह संभव हो सकता है #undef NULL और इसे कुछ निराकरण के लिए फिर से परिभाषित करें। ऐसा करने वाला कोई भी व्यक्ति गोली मारने का हकदार है।" यह मेरे अच्छे साहब ने मुझे जोर से
हंसाया

34

ऐसा प्रतीत होता है कि बहुत से लोग गलत समझते हैं कि NULL, '\ 0' और 0 के बीच क्या अंतर हैं। इसलिए, पहले बताई गई बातों को दोहराने से बचने के प्रयास में, और:

intमान 0 के साथ प्रकार की एक निरंतर अभिव्यक्ति , या इस प्रकार की अभिव्यक्ति, टाइप करने के लिए डाली गई void *एक अशक्त सूचक स्थिरांक है , जिसे यदि सूचक में परिवर्तित किया जाता है, तो यह शून्य सूचक बन जाता है । यह मानक द्वारा किसी भी वस्तु या कार्य के लिए किसी भी सूचक को असमान की तुलना करने की गारंटी है ।

NULLएक मैक्रो है, एक अशक्त सूचक स्थिरांक के रूप में परिभाषित किया गया है ।

\0एक निर्माण है जिसका उपयोग अशक्त चरित्र को दर्शाने के लिए किया जाता है, जिसका उपयोग स्ट्रिंग को समाप्त करने के लिए किया जाता है।

एक अशक्त चरित्र एक बाइट है जिसके सभी बिट्स 0 पर सेट हैं।


14

तीनों अलग-अलग संदर्भ में शून्य के अर्थ को परिभाषित करते हैं।

  • पॉइंटर का संदर्भ - NULL का उपयोग किया जाता है और इसका मतलब है कि पॉइंटर का मान 0 है, चाहे वह 32bit हो या 64bit (एक मामला 4 अन्य 8 बाइट्स ऑफ़ ज़ीरो) से स्वतंत्र है।
  • स्ट्रिंग संदर्भ - अंक शून्य का प्रतिनिधित्व करने वाले वर्ण का हेक्स मान 0x30 है, जबकि एनयूएल चरित्र का 0x00 का हेक्स मान है (स्ट्रिंग को समाप्त करने के लिए उपयोग किया जाता है)।

जब आप स्मृति को देखते हैं तो ये तीनों हमेशा अलग होते हैं:

NULL - 0x00000000 or 0x00000000'00000000 (32 vs 64 bit)
NUL - 0x00 or 0x0000 (ascii vs 2byte unicode)
'0' - 0x20

मुझे उम्मीद है कि यह इसे स्पष्ट करता है।


8
नास्को: मूल्यांकन करें sizeof('\0')और आश्चर्यचकित हो जाएं।
कैफ़े

3
@ नास्को: मैं वास्तव में आश्चर्यचकित था: जीसीसी के साथ, सी में: sizeof ('\ 0') == sizeof ('a') == 4, जबकि g ++ के साथ, C ++ में: sizeof ('\ 0') = - sizeof ('ए') == १
डेविड रॉड्रिग्ज - ड्रिग्ज

1
@ नास्को: सी मानक से (ड्राफ्ट, एन ११२४): 'एक पूर्णांक वर्ण स्थिरांक में टाइप int है', इस प्रकार '\ 0' वास्तव में C में टाइप का प्रकार है, और इस प्रकार sizeof ('\ 0') मेरी वास्तुकला में 4 है (linux, 32bit)
डेविड रोड्रिग्ज - ड्रिग्ज

@dribeas - मैं इसे एक स्थिर के रूप में वर्णित नहीं कर रहा था, बल्कि आप इसे स्ट्रिंग के भाग के रूप में देखेंगे। मैं निश्चित रूप से इसे स्पष्ट कर सकता था। धन्यवाद
नास्को

@ DavidRodríguez-dribeas Undid संपादित करें "Corrected '0' ASCII का मान 0x20 (32 से कम)"
chux - 19:18 पर मोनिका

6

यदि NULL और 0 नल सूचक के रूप में बराबर हैं, तो मुझे किसका उपयोग करना चाहिए? सी एफएफ़ सूची में इस मुद्दे को भी संबोधित करता है:

सी प्रोग्रामर को समझना चाहिए कि NULLऔर 0पॉइंटर संदर्भों में विनिमेय हैं, और यह कि एक अप्रकाशित 0 पूरी तरह से स्वीकार्य है। NULL के किसी भी उपयोग (जैसा कि विरोध किया गया 0) को एक सौम्य अनुस्मारक माना जाना चाहिए कि एक पॉइंटर शामिल है; प्रोग्रामर को 0पूर्णांक से सूचक के अलग होने के लिए इस पर (या तो अपनी समझ के लिए या संकलक के) पर निर्भर नहीं होना चाहिए 0

यह केवल सूचक संदर्भों में है जो समान हैं NULLऔर 0समतुल्य हैं। NULLदूसरी तरह की 0आवश्यकता होने पर भी इसका उपयोग नहीं किया जाना चाहिए , भले ही यह काम कर सकता है, क्योंकि ऐसा करने से गलत शैलीगत संदेश जाता है। (इसके अलावा, ANSI परिभाषा की अनुमति देता NULLहै ((void *)0), जो गैर-पॉइंटर संदर्भों में बिल्कुल भी काम नहीं करेगा।) विशेष रूप से, NULLASCII अशक्त चरित्र ( NUL) वांछित होने पर उपयोग न करें । अपनी खुद की परिभाषा प्रदान करें

#define NUL '\0'

यदि तुम्हे जरुरी हो।


5

NULL, '\ 0' और 0 में क्या अंतर है

"अशक्त चरित्र (NUL)" को शासन करना सबसे आसान है। '\0'एक चरित्र शाब्दिक है। सी में, इसे लागू किया जाता है int, इसलिए, यह 0 के समान है, जो कि है INT_TYPE_SIZE। सी ++ में, चरित्र शाब्दिक के रूप में कार्यान्वित किया जाता है char, जो 1 बाइट है। यह सामान्य रूप से अलग है NULLया 0

अगला, NULLएक पॉइंटर मूल्य है जो निर्दिष्ट करता है कि एक चर किसी भी पते की जगह को इंगित नहीं करता है। इस तथ्य को अलग करें कि इसे आम तौर पर शून्य के रूप में लागू किया जाता है, यह वास्तुकला का पूरा पता स्थान व्यक्त करने में सक्षम होना चाहिए। इस प्रकार, 32-बिट आर्किटेक्चर पर NULL (संभावना) 4-बाइट पर और 64-बिट आर्किटेक्चर 8-बाइट पर है। यह C के क्रियान्वयन तक है।

अंत में, शाब्दिक 0प्रकार का है int, जो आकार का है INT_TYPE_SIZEINT_TYPE_SIZEआर्किटेक्चर के आधार पर डिफ़ॉल्ट मूल्य अलग हो सकता है।

Apple ने लिखा:

मैक ओएस एक्स द्वारा उपयोग किए जाने वाले 64-बिट डेटा मॉडल को "एलपी 64" के रूप में जाना जाता है। यह सामान्य डेटा मॉडल है जो सूर्य और एसजीआई के साथ-साथ 64-बिट लिनक्स से 64-बिट यूनिक्स प्रणालियों द्वारा उपयोग किया जाता है। LP64 डेटा मॉडल आदिम प्रकारों को परिभाषित करता है:

  • ints 32-बिट हैं
  • लोंग 64-बिट हैं
  • लंबे-लंबे भी 64-बिट हैं
  • संकेत 64-बिट हैं

विकिपीडिया 64-बिट :

Microsoft का VC ++ कंपाइलर LLP64 मॉडल का उपयोग करता है।

64-bit data models
Data model short int long  long long pointers Sample operating systems
LLP64      16    32  32    64        64       Microsoft Win64 (X64/IA64)
LP64       16    32  64    64        64       Most Unix and Unix-like systems (Solaris, Linux, etc.)
ILP64      16    64  64    64        64       HAL
SILP64     64    64  64    64        64       ?

संपादित करें : चरित्र शाब्दिक पर अधिक जोड़ा गया।

#include <stdio.h>

int main(void) {
    printf("%d", sizeof('\0'));
    return 0;
}

उपरोक्त कोड gcc पर 4 और g ++ पर 1 रिटर्न देता है।


2
नहीं है, '\0'है एक 1-बाइट मूल्य। यह एक चरित्र शाब्दिक है, जो एक पूर्णांक स्थिर अभिव्यक्ति है - इसलिए अगर इसे आकार कहा जा सकता है तो यह एक int(जो कम से कम 2 बाइट्स होना चाहिए) का आकार है। यदि आप मुझ पर विश्वास नहीं करते हैं, तो मूल्यांकन करें sizeof('\0')और अपने लिए देखें। '\0', 0और 0x0सभी पूरी तरह से बराबर हैं।
कैफे

@ कैफ यह भाषा पर निर्भर करता है। यदि आप मुझ sizeof('\0')पर विश्वास नहीं करते हैं, तो C ++ कंपाइलर पर प्रयास करें ।
यूजीन योकोटा

2
साइज़ोफ़ (कुछ) प्रिंट करते समय आपको "% zu" का उपयोग करना चाहिए
अप्रयुक्त


4

एक अच्छा टुकड़ा जो सी के साथ शुरू होने पर मेरी मदद करता है (लिंडेन द्वारा विशेषज्ञ सी प्रोग्रामिंग से लिया गया)

एक 'एल' शून्य और दो 'एल' शून्य

संकेत और ASCII शून्य के लिए सही शब्दावली को याद करने के लिए इस छोटे कविता को याद करें:

The one "l" NUL ends an ASCII string,

The two "l" NULL points to no thing.

Apologies to Ogden Nash, but the three "l" nulll means check your spelling. 

शून्य के बिट पैटर्न के साथ ASCII वर्ण को "NUL" कहा जाता है। विशेष सूचक मान जिसका अर्थ है कि सूचक बिंदु "NULL" कहीं नहीं है। दो शब्द अर्थ में विनिमेय नहीं हैं।


बहुत सरल: NULइस तरह के रूप में एक नियंत्रण कोड है BEL, VT, HT, SOTआदि है और इस तरह अधिकतम है। 3 अक्षर।
Glglgl

2

"एनयूएल" 0 नहीं है, लेकिन एएससीआईआई एनयूएल चरित्र को संदर्भित करता है। कम से कम, यह है कि मैंने इसे कैसे देखा है। नल पॉइंटर को अक्सर 0 के रूप में परिभाषित किया जाता है, लेकिन यह उस वातावरण पर निर्भर करता है जिसमें आप चल रहे हैं, और जो भी ऑपरेटिंग सिस्टम या भाषा आप उपयोग कर रहे हैं उसके विनिर्देश।

एएनएसआई सी में, शून्य सूचक को पूर्णांक मान के रूप में निर्दिष्ट किया जाता है। 0. इसलिए कोई भी दुनिया जहां यह सच नहीं है एएनएसआई सी कंप्लेंट नहीं है।


1

एक मान के साथ एक बाइट 0x00, ASCII तालिका पर, विशेष वर्ण जिसे कहा जाता है NULया NULL। C में, चूंकि आप अपने स्रोत कोड में नियंत्रण वर्णों को एम्बेड नहीं कर सकते हैं, यह C तार में एक बची हुई 0, यानी के साथ दर्शाया गया है \0

लेकिन एक सच्चा NULL एक मूल्य नहीं है। यह मूल्य का अभाव है। एक पॉइंटर के लिए, इसका मतलब है कि पॉइंटर को इंगित करने के लिए कुछ भी नहीं है। एक डेटाबेस में, इसका मतलब है कि किसी क्षेत्र में कोई मूल्य नहीं है (जो कि क्षेत्र रिक्त है, 0, या रिक्त स्थान से भरा हुआ है) कहने के समान नहीं है।

वास्तविक मूल्य एक दिया प्रणाली या डेटाबेस फ़ाइल स्वरूप का प्रतिनिधित्व करने के लिए एक का उपयोग करता है NULLजरूरी नहीं है 0x00


0

NULL0 होने की गारंटी नहीं है - इसका सटीक मूल्य वास्तुकला पर निर्भर है। अधिकांश प्रमुख आर्किटेक्चर इसे परिभाषित करते हैं (void*)0

'\0' हमेशा 0 के बराबर होगा, क्योंकि यह है कि कैसे बाइट 0 एक चरित्र शाब्दिक में एन्कोडेड है।

मुझे याद नहीं है कि क्या C कंपाइलर्स को ASCII का उपयोग करना आवश्यक है - यदि नहीं, तो '0'हमेशा 48 के बराबर नहीं हो सकता। भले ही, यह संभावना नहीं है कि आप कभी भी एक ऐसी प्रणाली का सामना करेंगे जो EBCDIC जैसे वैकल्पिक वर्ण सेट का उपयोग करती है जब तक कि आप बहुत काम नहीं कर रहे हों अस्पष्ट प्रणाली।

विभिन्न प्रकार के आकार 64-बिट सिस्टम पर भिन्न होंगे, लेकिन पूर्णांक मान समान होंगे।


कुछ टिप्पणीकारों ने संदेह व्यक्त किया है कि NULL 0 के बराबर होना चाहिए, लेकिन शून्य नहीं होना चाहिए । इस तरह के सिस्टम पर अपेक्षित आउटपुट के साथ एक उदाहरण कार्यक्रम यहां दिया गया है:

#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;
}

वह कार्यक्रम प्रिंट कर सकता है:

NULL == 0
NULL = 0x00000001

2
ओपी '\ _' (एनयूएल चरित्र) के बारे में पूछ रहा था, न कि '0' (शून्य चरित्र)
क्रिस लुत्ज़

2
@ क्रिस: '\ 0' NULL नहीं है, यह एक वर्ण शाब्दिक में ऑक्टल में बाइट 0 है।
जॉन मिलिकिन

2
C ++ में, मानक गारंटी देता है कि पूर्णांक मान 0 से एक पॉइंटर में रूपांतरण हमेशा शून्य पॉइंटर प्राप्त करेगा। C ++ में, 0 को शून्य सूचक होने की गारंटी है, जबकि दूसरी तरफ NULL एक मैक्रो है और एक दुर्भावनापूर्ण कोडर इसे कुछ अलग के रूप में पुनर्परिभाषित कर सकता है।
डेविड रॉड्रिग्ज - drieaseas

6
और NULL की गारंटी दी जाती है। 0. NULL पॉइंटर का बिट पैटर्न सभी शून्य होने की गारंटी नहीं है, लेकिन NULL निरंतर है, और हमेशा रहेगा, 0.
jalf

2
आपका पहला वाक्य गलत है - C ++ में NULL को (void *) 0 के रूप में परिभाषित नहीं किया जा सकता है क्योंकि किसी void * से दूसरे पॉइंटर (C के विपरीत) में कोई निहित रूपांतरण नहीं है।

-2

(शून्य *) 0 NULL है, और '\ 0' एक स्ट्रिंग के अंत का प्रतिनिधित्व करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.