C में "a"? = "A" क्यों है?


110
void main() {
    if("a" == "a")
      printf("Yes, equal");  
    else
      printf("No, not equal");
}

आउटपुट क्यों है No, not equal?


100
void main??? इव ...
पॉल आर

47
एंबेडेड सी कंपाइलर शून्य मुख्य () की अनुमति देते हैं क्योंकि हो सकता है कि कोई भी ऑपरेटिंग सिस्टम रिटर्न कोड न दे।
जेने पिंडर

26
इस तरह का एक सवाल इतनी बार कैसे उठ सकता है? यह वास्तव में दिलचस्प नहीं है ... मेरा मतलब है, कि तार सरणियाँ हैं और सरणियाँ हैं संकेत वास्तव में सी में एक पुरानी टोपी है, है ना?
फेलिक्स डॉम्बेक

64
@ फेलिक्स, यह एक संक्षिप्त रूप से लिखित प्रश्न है जो भाषा के लिए नए लोगों के लिए भ्रम का एक सामान्य बिंदु है। SO केवल विशेषज्ञों के लिए नहीं है - यह शुरुआती लोगों के लिए भी है, और इस तरह के लक्षित प्रश्न भविष्य में शुरुआती लोगों को संदर्भित करने के लिए अच्छे हैं।
bdonlan

37
@ फेलिक्स: आप गलत हैं। सरणियाँ संकेत नहीं हैं
जॉन डिब्लिंग 20

जवाबों:


209

आप जो तुलना कर रहे हैं वह अलग-अलग तारों के लिए दो मेमोरी पते हैं, जो विभिन्न स्थानों में संग्रहीत हैं। ऐसा करना अनिवार्य रूप से इस तरह दिखता है:

if(0x00403064 == 0x002D316A) // Two memory locations
{
    printf("Yes, equal");
}

दो स्ट्रिंग मानों की तुलना करने के लिए निम्न कोड का उपयोग करें:

#include <string.h>

...

if(strcmp("a", "a") == 0)
{
    // Equal
}

इसके अतिरिक्त, "a" == "a"आपके कंपाइलर के आधार पर वास्तव में सही वापसी हो सकती है, जो अंतरिक्ष को बचाने के लिए संकलन समय में बराबर तारों को जोड़ सकती है।

जब आप दो चरित्र मानों (जो संकेत नहीं हैं) की तुलना कर रहे हैं, तो यह एक संख्यात्मक तुलना है। उदाहरण के लिए:

'a' == 'a' // always true

12
GCC में भी विकल्प हैं -fmerge-constantsऔर -fno-merge-constantsस्ट्रिंग / फ़्लोटिंग-पॉइंट-निरंतर स्थिरांक को अनुवाद इकाइयों में सक्षम / अक्षम करने के लिए, हालाँकि कुछ GCC पर ऐसा लगता है कि निरंतर विलय हमेशा उस विकल्प की परवाह किए बिना सक्षम होता है।
एडम रोसेनफील्ड

2
यदि आप "a" के बजाय 'a' का उपयोग करते हैं तो यह काम करेगा। पहला एक चार है, जो वास्तव में एक संख्यात्मक मूल्य है।
GolezTrol

@GolezTrol: सी में, शाब्दिक 'ए' वास्तव में intप्रकार है। :-) इसके अलावा, संकेत संख्यात्मक मान नहीं है।
बैस्टियन लेओनार्ड

intसंख्यात्मक भी है, है ना? लेकिन मुझे लगा कि बाइट्स बाइट थे। इंट 4 बाइट्स है। संकेत स्वयं पूर्णांक भी हैं। उनमें डेटा के एक समूह का पता होता है (डेटा जो वास्तव में संख्यात्मक नहीं होता है)।
गोलजट्रोल

'a' == 'A' // not true... MySQL अलग करने के लिए भीख माँगती है।
स्टीवन

52

मुझे पार्टी में थोड़ी देर हो गई है, लेकिन मैं वैसे भी जवाब देने जा रहा हूं; तकनीकी रूप से एक ही बिट्स, लेकिन थोड़ा अलग नजरिए से (नीचे सी पार्लेंस):

सी में, अभिव्यक्ति "a"एक स्ट्रिंग शाब्दिक दर्शाती है , जो एक स्थिर अनाम सरणी है const char, जिसमें दो की लंबाई होती है - सरणी में वर्ण होते हैं 'a'और '\0'- समाप्त करने वाला अशक्त वर्ण स्ट्रिंग के अंत को दर्शाता है ।

हालाँकि, C में, उसी तरह से आप एरर्स को वैल्यू द्वारा फंक्शन्स में पास नहीं कर सकते हैं - या उन्हें वैल्यू असाइन कर सकते हैं ( इनिशियलाइज़ेशन के बाद ) - ==एरेज़ के लिए कोई ओवरलोड ऑपरेटर नहीं है, इसलिए सीधे उनकी तुलना करना संभव नहीं है। विचार करें

int a1[] = {1, 2, 3};
int a2[] = {3, 4, 5};
a1 == a2 // is this meaningful? Yes and no; it *does* compare the arrays for
         // "identity", but not for their values. In this case the result
         // is always false, because the arrays (a1 and a2) are distinct objects

यदि ==सरणियों की तुलना नहीं कर रहा है, तो यह वास्तव में क्या करता है, फिर? C में, लगभग सभी संदर्भों में - इसमें एक - सरणियों का संकेत बिंदुओं में क्षय होता है (जो कि सरणी के पहले तत्व को इंगित करता है) - और समानता के लिए बिंदुओं की तुलना वह करता है जिसकी आप अपेक्षा करते हैं। इतना प्रभावी, जब यह कर रहा है

"a" == "a"

आप वास्तव में दो अनाम सरणियों में पहले वर्णों के पतों की तुलना कर रहे हैं । सी मानक के अनुसार, तुलना या तो सही या गलत हो सकती है (यानी 1 या 0) - "a"एस वास्तव में एक ही सरणी या दो पूरी तरह से असंबंधित सरणियों को निरूपित कर सकता है। तकनीकी शब्दों में, परिणामी मूल्य अनिर्दिष्ट है , जिसका अर्थ है कि तुलना की अनुमति है (अर्थात यह अपरिभाषित व्यवहार या वाक्यविन्यास त्रुटि नहीं है), लेकिन या तो मान मान्य है और वास्तव में क्या होगा, इसे लागू करने के लिए (आपके संकलक) की आवश्यकता नहीं है।

जैसा कि दूसरों ने बताया है, "सी स्ट्रिंग्स" (यानी एक अशक्त चरित्र के साथ समाप्त होने वाले तार) की तुलना करने के लिए आप strcmpमानक हेडर फ़ाइल में पाए गए सुविधा फ़ंक्शन का उपयोग करते हैं string.h। फ़ंक्शन में 0समान स्ट्रिंग्स के लिए वापसी मान है ; यह स्पष्ट रूप 0से ऑपरेटर `का उपयोग करने के बजाय वापसी मूल्य की तुलना करने के लिए अच्छा अभ्यास माना जाता है ! ie, यानी

strcmp(str1, str2) == 0 // instead of !strcmp(str1, str2)

47

C99 के अनुसार (धारा 6.4.5 / 6)

स्ट्रिंग लिटरल

यह अनिर्दिष्ट है कि क्या ये सरणियाँ विशिष्ट हैं बशर्ते कि उनके तत्वों में उचित मूल्य हों

तो इस मामले में यह अनिर्दिष्ट है कि क्या दोनों "a"अलग हैं। एक अनुकूलित संकलक "a"रीड-ओनली लोकेशन में एकल रख सकता है और दोनों संदर्भों को संदर्भित कर सकता है।

यहां gcc पर आउटपुट देखें


19

क्योंकि वे 2 अलग हैं const char*, संकेत, कोई वास्तविक मूल्य नहीं है। आप ऐसा कुछ कह रहे हैं, 0x019181217 == 0x0089178216जो निश्चित रूप से नहीं लौटाता है

के strcmp()बजाय का उपयोग करें==


7
स्ट्रिंग शाब्दिक बिंदु नहीं हैं, वे सरणियाँ हैं। वे तुलना पर संकेत करने के लिए क्षय, यद्यपि।
GManNickG

@Gman सच है, उस पर वास्तव में स्पष्ट नहीं होने के लिए खेद है, इसे भूल जाते हैं :)
Antwan van Houdt

9

सीधे शब्दों में कहें, सी में कोई अंतर्निहित स्ट्रिंग तुलना ऑपरेटर नहीं है। यह इस तरह तार की तुलना नहीं कर सकता है।

इसके बजाय, स्ट्रिंग की तुलना मानक लाइब्रेरी रूटीन जैसे स्ट्रैम्प () या स्ट्रिंग में प्रत्येक वर्ण के माध्यम से लूप में कोड लिखकर की जाती है।

सी में, दोहरे उद्धरण चिह्नों में एक स्ट्रिंग स्ट्रिंग के लिए एक सूचक लौटाता है। आपका उदाहरण पॉइंटर्स की तुलना कर रहा है, और स्पष्ट रूप से आपके दो संस्करण स्ट्रिंग अलग-अलग पते पर मौजूद हैं।

लेकिन यह स्ट्रिंग्स की खुद से तुलना नहीं कर रहा है, जैसा कि आप उम्मीद करते हैं।


3

संकेत दिए गए।

पहला "a"एक अशक्त-समाप्त ASCII स्ट्रिंग का सूचक है।

दूसरा "a"एक और अशक्त-टर्म ASCII स्ट्रिंग का सूचक है।

यदि आप 32-बिट संकलक का उपयोग कर रहे हैं, तो मुझे उम्मीद है "a"=="a"-4। मैंने अभी इसे tcc / Win32 के साथ आज़माया है, और मुझे मिलता है "a"=="a"-2। ओह अच्छा...


6
आप स्ट्रिंग को 4-बाइट सीमा से संरेखित करने की अपेक्षा क्यों करेंगे? वे ints नहीं हैं। 2 वह है जो मैं उम्मीद करूंगा (यदि कंपाइलर उन्हें मर्ज नहीं करता है), क्योंकि प्रत्येक स्ट्रिंग दो बाइट्स लंबा है, जिसमें शून्य टर्मिनेटर भी शामिल है।
सेर्गेई टैचेनोव

उदाहरण के लिए, कुछ डिग्री संरेखण strcmpएक समय में कई बाइट्स चलाने की अनुमति दे सकता है। कुछ संकलक ऐसा करते हैं, कुछ नहीं करते हैं, कुछ केवल कुछ न्यूनतम की तुलना में लंबे समय तक तार के लिए करते हैं ...
zwol

@Zack: वास्तव में उनकी तुलना करने से पहले उन्हें स्ट्रिंग की लंबाई कैसे पता चलेगी?
जोआचिम सॉउर

मेरा मतलब था, कुछ संकलक कुछ न्यूनतम की तुलना में लंबे समय तक तार संरेखित करते हैं।
zwol

1

आप दो मेमोरी एड्रेस की तुलना कर रहे हैं, इसलिए परिणाम हमेशा सही नहीं होगा। क्या आपने कोशिश की if('a' == 'a'){...}?


1

यह प्रश्न सभी शुरुआती लोगों के लिए स्पष्टीकरण का बहुत अच्छा निशान स्थापित करता है ....
मुझे भी इसमें योगदान करने दें .....

जैसा कि ऊपर सभी को बताया गया है कि आपको ऐसा आउटपुट क्यों मिल रहा है।

अब अगर आप अपना प्रोग चाहते हैं। फिर "हाँ बराबर" मुद्रित करने के लिए

या तो उपयोग करें

if(strcmp("a", "a") == 0)
{

}

या
स्ट्रिंग्स के रूप में "a" का उपयोग न करें, उन्हें वर्णों के रूप में उपयोग करें ...।

if('a'=='a')  
{  
printf ("yes Equal");  
}  

C अक्षरों में 1 बाइट लघु पूर्णांक हैं ......।


वर्ण केवल 1 बाइट पर कब्जा करते हैं, लेकिन चरित्र शाब्दिक, जैसे कि 'a'वास्तव में पूर्णांक हैं।
स्प्रेडी

0

कुछ संकलक में 'मर्ज स्ट्रिंग्स' विकल्प होता है, जिसका उपयोग करके आप सभी निरंतर स्ट्रिंग्स को एक ही पते के लिए बाध्य कर सकते हैं। यदि आप इसका उपयोग करेंगे, "a" == "a"तो होगा true


0

यदि चरित्र के बीच तुलना हमेशा एकल उद्धरण में होती है, जैसे

if('a' == 'a')

और C स्ट्रिंग तुलना का समर्थन नहीं कर सकता "abc" == "abc"

के साथ किया है strcmp("abc","abc")


-5

यह आदमी चर का उपयोग नहीं करता है। इसके बजाय, वह अस्थायी रूप से पाठ सरणियों का उपयोग करता है: aऔर a। कारण क्यों

void main() 
{
    if("a" == "a")
      printf("Yes, equal");  
    else
      printf("No, not equal");
}

बेशक काम नहीं करता है, यह है कि आप चर की तुलना नहीं करते हैं।
यदि आप चर बनाएंगे जैसे:

char * text = "a";
char * text2 = "a";

तो आप के textसाथ तुलना कर सकते हैं text2, और यह सच होना चाहिए

हो सकता है कि आप उपयोग करना न भूलें {और }=)

void main() {
    if("a" == "a")
    {
      printf("Yes, equal");
    }
    else
    {
      printf("No, not equal");
    }
}

1
" और यह सच होना चाहिए " - नहीं। यह अनिर्दिष्ट है कि क्या स्ट्रिंग शाब्दिक को एक ही मेमोरी स्थान में संग्रहीत किया जाएगा। अन्य उत्तर पढ़ें।
स्पिकैट्रिक्स 10
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.