#include<stdio.h>
#include<string.h>
int main()
{
char * p = "abc";
char * p1 = "abc";
printf("%d %d", p, p1);
}
जब मैं दो बिंदुओं के मूल्यों को प्रिंट करता हूं, तो यह उसी पते को प्रिंट कर रहा है। क्यों?
#include<stdio.h>
#include<string.h>
int main()
{
char * p = "abc";
char * p1 = "abc";
printf("%d %d", p, p1);
}
जब मैं दो बिंदुओं के मूल्यों को प्रिंट करता हूं, तो यह उसी पते को प्रिंट कर रहा है। क्यों?
p
और का पता ले लिया है p1
, तो आपने देखा होगा कि ये दो बिंदु दो अलग-अलग पते के तहत संग्रहीत हैं। तथ्य यह है कि उनका मूल्य समान है - इस मामले में - अप्रासंगिक।
p == p1
(वे भिन्न नहीं हैं) लेकिन &p != &p1
(वे भिन्न होते हैं)।
जवाबों:
क्या एक ही सामग्री वाले दो अलग-अलग स्ट्रिंग शाब्दिक एक ही मेमोरी लोकेशन में रखे गए हैं या अलग-अलग मेमोरी लोकेशन कार्यान्वयन-निर्भर हैं।
तुम हमेशा व्यवहार करना चाहिए p
और p1
दो अलग अलग संकेत (भले ही वे एक ही सामग्री है) वे कर सकते हैं या एक ही पते पर बात नहीं हो सकता है के रूप में के रूप में। आपको संकलक अनुकूलन पर भरोसा नहीं करना चाहिए।
सी 11 मानक, 6.4.5, स्ट्रिंग शाब्दिक, शब्दार्थ
यह अनिर्दिष्ट है कि क्या ये सरणियाँ विशिष्ट हैं बशर्ते कि उनके तत्वों में उचित मूल्य हों। यदि प्रोग्राम ऐसे सरणी को संशोधित करने का प्रयास करता है, तो व्यवहार अपरिभाषित है।
मुद्रण के लिए प्रारूप होना चाहिए %p
:
printf("%p %p", (void*)p, (void*)p1);
यह उत्तर क्यों देखें ।
i modify one of the pointer, will the data in the other pointed also be modified
आप सूचक को संशोधित कर सकते हैं लेकिन स्ट्रिंग शाब्दिक को नहीं। उदाहरण char *p="abc"; p="xyz";
पूरी तरह से ठीक है जबकि अपरिभाषित व्यवहार कोchar *p="abc"; p[0]='x';
आमंत्रित करता है । इससे कोई लेना-देना नहीं है volatile
। चाहे आप उपयोग करें volatile
या न करें, हमारे यहाँ कोई भी व्यवहार नहीं बदलना चाहिए। volatile
मूल रूप से हर बार मेमोरी से डेटा पढ़ने के लिए मजबूर करता है।
p
स्ट्रिंग शाब्दिक को इंगित करता है "abc"
और p[0]='x'
एक स्ट्रिंग शाब्दिक के पहले चार को संशोधित करने का प्रयास करता है। एक स्ट्रिंग शाब्दिक को संशोधित करने का प्रयास सी। में अपरिभाषित व्यवहार है
char []
सी में शाब्दिक प्रकार का है । इसलिए इसे केवल पढ़ने के लिए ( const char*
जैसा कि C ++ में मामला है) को टाइप करने के साथ ही जप भी करना होगा । [contd।]
"Strings are no longer modifiable, and so may be placed in read-only memory"
एक ऐतिहासिक प्रमाण जो स्ट्रिंग शाब्दिक रूप से प्रयोग किया जाता है;;
आपका संकलक काफी चतुर प्रतीत होता है, यह पता लगाता है कि दोनों शाब्दिक एक ही हैं। और जैसा कि शाब्दिक निरंतर हैं संकलक ने उन्हें दो बार स्टोर नहीं करने का फैसला किया है।
यह उल्लेख के लायक है कि यह जरूरी नहीं कि मामला होना चाहिए। कृपया इस पर ब्लू मून का जवाब देखें ।
Btw: printf()
बयान इस तरह दिखना चाहिए
printf("%p %p", (void *) p, (void *) p1);
जैसा कि "%p"
सूचक मानों को प्रिंट करने के लिए उपयोग किया जाएगा, और यह void *
केवल प्रकार के सूचक के लिए परिभाषित किया गया है । * 1
इसके अलावा, मैं कहूंगा कि कोड एक return
बयान याद करता है, लेकिन सी मानक बदलने की प्रक्रिया में है। अन्य कृपया इसे स्पष्ट करें।
* 1: void *
यहाँ पर कास्टिंग करना char *
पॉइंटर्स के लिए नहीं , बल्कि पॉइंटर्स के लिए अन्य सभी प्रकारों के लिए आवश्यक है ।
==
उपयोग करना चाहिए दो स्ट्रिंग्स (यहां तक कि सूचक) की तुलना करना चाहिए strcmpy()
। क्योंकि अन्य कंपाइलर ऑप्टिमाइज़ेशन का उपयोग नहीं कर रहे होंगे (यह कंपाइलर - कार्यान्वयन प्रतिनियुक्ति तक है) क्योंकि Alk PS ने उत्तर दिया: ब्लू मून अभी इसके बारे में जोड़ा गया है।
आपके संकलक ने "स्ट्रिंग पूलिंग" नामक कुछ किया है। आपने निर्दिष्ट किया कि आप दो पॉइंटर्स चाहते थे, दोनों एक ही स्ट्रिंग शाब्दिक की ओर इशारा करते हैं - इसलिए इसने केवल शाब्दिक की एक प्रति बनाई।
तकनीकी रूप से: यह संकेतकर्ताओं को "कॉन्स्ट" न बनाने के लिए आपसे शिकायत करनी चाहिए थी
const char* p = "abc";
यह संभवतः इसलिए है क्योंकि आप विजुअल स्टूडियो का उपयोग कर रहे हैं या आप बिना जीसीसी का उपयोग कर रहे हैं।
यदि आप स्पष्ट रूप से चाहते हैं कि उन्हें दो बार मेमोरी में संग्रहीत किया जाए, तो प्रयास करें:
char s1[] = "abc";
char s2[] = "abc";
यहां आप स्पष्ट रूप से कहते हैं कि आप दो सी-कैरेक्टर एरर चाहते हैं बजाय दो पॉइंटर्स टू कैरेक्टर।
कैविएट: स्ट्रिंग पूलिंग एक कंपाइलर / ऑप्टिमाइज़र सुविधा है न कि भाषा का एक पहलू। विभिन्न वातावरणों के तहत इस तरह के अलग-अलग संकलक अनुकूलन स्तर, संकलक झंडे और क्या तार अलग-अलग संकलनों इकाइयों में हैं, के आधार पर अलग-अलग व्यवहार का उत्पादन करेंगे।
gcc (Debian 4.4.5-8) 4.4.5
शिकायत (चेतावनी) नहीं है, हालांकि का उपयोग कर -Wall -Wextra -pedantic
।
const
स्ट्रिंग शाब्दिकों के लिए उपयोग नहीं करने के बारे में चेतावनी नहीं देता है। चेतावनी विकल्प द्वारा सक्षम है -Wwrite-strings
। यह स्पष्ट रूप से किसी अन्य विकल्प (जैसे -Wall
, -Wextra
या -pedantic
) द्वारा सक्षम नहीं है ।
जैसा कि दूसरों ने कहा है, संकलक ध्यान दे रहा है कि उनके पास समान मूल्य है, और इसलिए अंतिम निष्पादन योग्य में डेटा साझा करने का निर्णय ले रहा है। लेकिन यह कट्टर हो जाता है: जब मैं निम्नलिखित संकलन करता हूंgcc -O
#include<stdio.h>
#include<string.h>
int main()
{
char * p = "abcdef";
char * p1 = "def";
printf("%d %d", p, p1);
}
यह 4195780 4195783
मेरे लिए प्रिंट करता है। यही है, p1
3 बाइट्स के बाद शुरू होता है p
, इसलिए जीसीसी ने def
( \0
टर्मिनेटर सहित ) के सामान्य प्रत्यय को देखा है और आपके द्वारा दिखाए गए समान अनुकूलन किया है।
(यह एक जवाब है क्योंकि यह एक टिप्पणी होने के लिए बहुत लंबा है।)
कोड में स्ट्रिंग शाब्दिक कोड के केवल-पढ़ने के लिए डेटा खंड में संग्रहीत होते हैं। जब आप "abc" जैसे एक स्ट्रिंग शाब्दिक लिखते हैं, तो यह वास्तव में एक 'const char *' देता है और यदि आपके पास इस पर सभी संकलक चेतावनी थी, तो आपको बताएगा कि आप उस बिंदु पर कास्टिंग कर रहे हैं। आपको इस प्रश्न में इंगित किए गए कारण के लिए उन तारों को बदलने की अनुमति नहीं है।
जब आप एक स्ट्रिंग शाब्दिक ("एबीसी") बनाते हैं, तो इसे एक मेमोरी में सहेजा जाता है, जिसमें स्ट्रिंग शाब्दिक शामिल होते हैं, और फिर इसे पुन: उपयोग किया जाता है यदि आप एक ही स्ट्रिंग शाब्दिक का संदर्भ देते हैं, इस प्रकार दोनों संकेत एक ही स्थान पर इंगित करते हैं, जहां " abc "स्ट्रिंग शाब्दिक संग्रहित है।
मैंने इसे कुछ समय पहले सीखा है इसलिए मैंने इसे स्पष्ट रूप से स्पष्ट रूप से नहीं समझा, क्षमा करें।
यह वास्तव में निर्भर करता है कि आप किस कंपाइलर का उपयोग कर रहे हैं ।
टीसी ++ 3.5 के साथ मेरे सिस्टम में यह दो पॉइंटर्स के लिए दो अलग-अलग मानों को प्रिंट करता है यानी दो अलग-अलग पते ।
आपका संकलक यह होगा सेंट बनाया गया है स्मृति में किसी भी मूल्य के होने की जाँच और अपने अस्तित्व के आधार पर पुन: असाइन होगा या एक ही संदर्भ का उपयोग करता है, तो एक ही मूल्य में जाना जाता है पहले से संग्रहीत मूल्य की।
इसलिए इसके बारे में बहुत ज्यादा न सोचें क्योंकि यह कोड संकलक के तरीके पर निर्भर करता है ।
यह कंपाइलर ऑप्टिमाइज़ेशन है लेकिन पोर्टेबिलिटी के लिए ऑप्टिमाइज़ेशन को भूल जाते हैं। कुछ समय में संकलित कोड वास्तविक कोड से अधिक पठनीय होते हैं।