दो स्ट्रिंग पॉइंटर्स से लेकर अलग-अलग स्ट्रिंग लिटरल्स के पते एक जैसे हैं


80

जब मैं दो बिंदुओं के मूल्यों को प्रिंट करता हूं, तो यह उसी पते को प्रिंट कर रहा है। क्यों?


66
आपको क्यों लगता है कि यह नहीं करना चाहिए ये दोनों संकेत ठीक एक ही बात की ओर इशारा करते हैं। आप जो देख रहे हैं वह शायद स्ट्रिंग पूलिंग नामक एक अनुकूलन तकनीक का प्रभाव है।
डैनियल कामिल कोजार

2
भले ही डेटा समान है लेकिन चर अलग-अलग हैं।
सेरेड्डी सेखर

2
चर, ज़ाहिर है, अलग हैं। यदि आपने pऔर का पता ले लिया है p1, तो आपने देखा होगा कि ये दो बिंदु दो अलग-अलग पते के तहत संग्रहीत हैं। तथ्य यह है कि उनका मूल्य समान है - इस मामले में - अप्रासंगिक।
डैनियल कामिल कोजार सेप

हां, यदि मैं मान बदलता हूं तो पते अलग हैं।
सेररेड्डी सेखर

11
@ जानहुडेक: प्रश्न को फिर से पढ़ें। इस मामले में (संकलक अनुकूलन के कारण) p == p1(वे भिन्न नहीं हैं) लेकिन &p != &p1(वे भिन्न होते हैं)।
MSALERS

जवाबों:


87

क्या एक ही सामग्री वाले दो अलग-अलग स्ट्रिंग शाब्दिक एक ही मेमोरी लोकेशन में रखे गए हैं या अलग-अलग मेमोरी लोकेशन कार्यान्वयन-निर्भर हैं।

तुम हमेशा व्यवहार करना चाहिए pऔर p1दो अलग अलग संकेत (भले ही वे एक ही सामग्री है) वे कर सकते हैं या एक ही पते पर बात नहीं हो सकता है के रूप में के रूप में। आपको संकलक अनुकूलन पर भरोसा नहीं करना चाहिए।

सी 11 मानक, 6.4.5, स्ट्रिंग शाब्दिक, शब्दार्थ

यह अनिर्दिष्ट है कि क्या ये सरणियाँ विशिष्ट हैं बशर्ते कि उनके तत्वों में उचित मूल्य हों। यदि प्रोग्राम ऐसे सरणी को संशोधित करने का प्रयास करता है, तो व्यवहार अपरिभाषित है।


मुद्रण के लिए प्रारूप होना चाहिए %p:

यह उत्तर क्यों देखें ।


मैंने अस्थिरता का उपयोग किया ताकि कोई स्मृति अनुकूलन न हो, यहां तक ​​कि वे एक ही पता भी लेते हैं। एक प्रश्न यह है कि यदि मैं पॉइंटर में से एक को संशोधित करता हूं, तो क्या अन्य बिंदुओं में डेटा को भी संशोधित किया जाएगा।
मेघराज

8
@ मेघराज 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मूल रूप से हर बार मेमोरी से डेटा पढ़ने के लिए मजबूर करता है।
पीपी

2
@ शशरथ हगडे। क्योंकि pस्ट्रिंग शाब्दिक को इंगित करता है "abc"और p[0]='x'एक स्ट्रिंग शाब्दिक के पहले चार को संशोधित करने का प्रयास करता है। एक स्ट्रिंग शाब्दिक को संशोधित करने का प्रयास सी। में अपरिभाषित व्यवहार है
पीपी

2
@ शारथ हेजडे क्योंकि सी मानक बताता है कि। इसका कारण मुख्य रूप से ऐतिहासिक है क्योंकि पूर्व-मानक सी भाषा में स्ट्रिंग स्ट्रिंग को संशोधित करने की अनुमति है। बाद में, C मानक (C89) ने इसे अपरिभाषित कर दिया, ताकि नया कोड ऐसा न करे और पुराने कोड (पूर्व-मानक) कार्य वे थे। मूल रूप से यह मौजूदा (पूर्व-स्टेनार्ड) कोड को नहीं तोड़ने का एक समझौता है, मेरा मानना ​​है। एक अन्य कारण char []सी में शाब्दिक प्रकार का है । इसलिए इसे केवल पढ़ने के लिए ( const char*जैसा कि C ++ में मामला है) को टाइप करने के साथ ही जप भी करना होगा । [contd।]
पीपी

7
परिशिष्ट C में K & R 2nd संस्करण में एक पंक्ति है: "Strings are no longer modifiable, and so may be placed in read-only memory"एक ऐतिहासिक प्रमाण जो स्ट्रिंग शाब्दिक रूप से प्रयोग किया जाता है;;
PP

28

आपका संकलक काफी चतुर प्रतीत होता है, यह पता लगाता है कि दोनों शाब्दिक एक ही हैं। और जैसा कि शाब्दिक निरंतर हैं संकलक ने उन्हें दो बार स्टोर नहीं करने का फैसला किया है।

यह उल्लेख के लायक है कि यह जरूरी नहीं कि मामला होना चाहिए। कृपया इस पर ब्लू मून का जवाब देखें ।


Btw: printf()बयान इस तरह दिखना चाहिए

जैसा कि "%p"सूचक मानों को प्रिंट करने के लिए उपयोग किया जाएगा, और यह void *केवल प्रकार के सूचक के लिए परिभाषित किया गया है । * 1


इसके अलावा, मैं कहूंगा कि कोड एक returnबयान याद करता है, लेकिन सी मानक बदलने की प्रक्रिया में है। अन्य कृपया इसे स्पष्ट करें।


* 1: void *यहाँ पर कास्टिंग करना char *पॉइंटर्स के लिए नहीं , बल्कि पॉइंटर्स के लिए अन्य सभी प्रकारों के लिए आवश्यक है ।


धन्यवाद। तो निष्कर्ष संकलक अनुकूलन सही है? डिफ़ॉल्ट रिटर्न द्वारा सी मुख्य समारोह में 0
seereddi sekhar

@seereddisekhar: हाँ, यह एक तरह का अनुकूलन है।
alk

2
@seereddisekhar लेकिन सावधान रहें इसका मतलब यह नहीं है कि आपको फ़ंक्शन का ==उपयोग करना चाहिए दो स्ट्रिंग्स (यहां तक ​​कि सूचक) की तुलना करना चाहिए strcmpy()। क्योंकि अन्य कंपाइलर ऑप्टिमाइज़ेशन का उपयोग नहीं कर रहे होंगे (यह कंपाइलर - कार्यान्वयन प्रतिनियुक्ति तक है) क्योंकि Alk PS ने उत्तर दिया: ब्लू मून अभी इसके बारे में जोड़ा गया है।
बृजेश चौहान सेप

2
प्रिय @Megharaj: क्या मैं इस पर एक अलग सवाल उठाने के लिए कह सकता हूं? आप इस नए प्रश्न का लिंक यहां टिप्पणी के रूप में पोस्ट कर सकते हैं।
एल्क

1
@ मेघराज: आप एक स्ट्रिंग शाब्दिक का मान नहीं बदल सकते। जैसा कि मैंने अपने प्रश्न में उल्लेख किया है, यह निरंतर है।
एल्क

18

आपके संकलक ने "स्ट्रिंग पूलिंग" नामक कुछ किया है। आपने निर्दिष्ट किया कि आप दो पॉइंटर्स चाहते थे, दोनों एक ही स्ट्रिंग शाब्दिक की ओर इशारा करते हैं - इसलिए इसने केवल शाब्दिक की एक प्रति बनाई।

तकनीकी रूप से: यह संकेतकर्ताओं को "कॉन्स्ट" न बनाने के लिए आपसे शिकायत करनी चाहिए थी

यह संभवतः इसलिए है क्योंकि आप विजुअल स्टूडियो का उपयोग कर रहे हैं या आप बिना जीसीसी का उपयोग कर रहे हैं।

यदि आप स्पष्ट रूप से चाहते हैं कि उन्हें दो बार मेमोरी में संग्रहीत किया जाए, तो प्रयास करें:

यहां आप स्पष्ट रूप से कहते हैं कि आप दो सी-कैरेक्टर एरर चाहते हैं बजाय दो पॉइंटर्स टू कैरेक्टर।

कैविएट: स्ट्रिंग पूलिंग एक कंपाइलर / ऑप्टिमाइज़र सुविधा है न कि भाषा का एक पहलू। विभिन्न वातावरणों के तहत इस तरह के अलग-अलग संकलक अनुकूलन स्तर, संकलक झंडे और क्या तार अलग-अलग संकलनों इकाइयों में हैं, के आधार पर अलग-अलग व्यवहार का उत्पादन करेंगे।


1
gcc (Debian 4.4.5-8) 4.4.5शिकायत (चेतावनी) नहीं है, हालांकि का उपयोग कर -Wall -Wextra -pedantic
एल्क

1
हां, जैसा कि डिफ़ॉल्ट रूप से V4.8.1 gcc constस्ट्रिंग शाब्दिकों के लिए उपयोग नहीं करने के बारे में चेतावनी नहीं देता है। चेतावनी विकल्प द्वारा सक्षम है -Wwrite-strings। यह स्पष्ट रूप से किसी अन्य विकल्प (जैसे -Wall, -Wextraया -pedantic) द्वारा सक्षम नहीं है ।
सेल्के

1
दोनों GCC 4.4.7 और 4.7.2 मुझे या बिना-चेतावनी के चेतावनी देते हैं। pastebin.com/1DtYEzUN
kfsone

15

जैसा कि दूसरों ने कहा है, संकलक ध्यान दे रहा है कि उनके पास समान मूल्य है, और इसलिए अंतिम निष्पादन योग्य में डेटा साझा करने का निर्णय ले रहा है। लेकिन यह कट्टर हो जाता है: जब मैं निम्नलिखित संकलन करता हूंgcc -O

यह 4195780 4195783मेरे लिए प्रिंट करता है। यही है, p13 बाइट्स के बाद शुरू होता है p, इसलिए जीसीसी ने def( \0टर्मिनेटर सहित ) के सामान्य प्रत्यय को देखा है और आपके द्वारा दिखाए गए समान अनुकूलन किया है।

(यह एक जवाब है क्योंकि यह एक टिप्पणी होने के लिए बहुत लंबा है।)


3

कोड में स्ट्रिंग शाब्दिक कोड के केवल-पढ़ने के लिए डेटा खंड में संग्रहीत होते हैं। जब आप "abc" जैसे एक स्ट्रिंग शाब्दिक लिखते हैं, तो यह वास्तव में एक 'const char *' देता है और यदि आपके पास इस पर सभी संकलक चेतावनी थी, तो आपको बताएगा कि आप उस बिंदु पर कास्टिंग कर रहे हैं। आपको इस प्रश्न में इंगित किए गए कारण के लिए उन तारों को बदलने की अनुमति नहीं है।


2

जब आप एक स्ट्रिंग शाब्दिक ("एबीसी") बनाते हैं, तो इसे एक मेमोरी में सहेजा जाता है, जिसमें स्ट्रिंग शाब्दिक शामिल होते हैं, और फिर इसे पुन: उपयोग किया जाता है यदि आप एक ही स्ट्रिंग शाब्दिक का संदर्भ देते हैं, इस प्रकार दोनों संकेत एक ही स्थान पर इंगित करते हैं, जहां " abc "स्ट्रिंग शाब्दिक संग्रहित है।

मैंने इसे कुछ समय पहले सीखा है इसलिए मैंने इसे स्पष्ट रूप से स्पष्ट रूप से नहीं समझा, क्षमा करें।


2

यह वास्तव में निर्भर करता है कि आप किस कंपाइलर का उपयोग कर रहे हैं

टीसी ++ 3.5 के साथ मेरे सिस्टम में यह दो पॉइंटर्स के लिए दो अलग-अलग मानों को प्रिंट करता है यानी दो अलग-अलग पते

आपका संकलक यह होगा सेंट बनाया गया है स्मृति में किसी भी मूल्य के होने की जाँच और अपने अस्तित्व के आधार पर पुन: असाइन होगा या एक ही संदर्भ का उपयोग करता है, तो एक ही मूल्य में जाना जाता है पहले से संग्रहीत मूल्य की।

इसलिए इसके बारे में बहुत ज्यादा न सोचें क्योंकि यह कोड संकलक के तरीके पर निर्भर करता है

बस इतना ही...


1

क्योंकि स्ट्रिंग "एबीसी" खुद को स्मृति में एक पता है। जब आप फिर से "एबीसी" लिखते हैं तो यह उसी पते को संग्रहीत करता है


1

यह कंपाइलर ऑप्टिमाइज़ेशन है लेकिन पोर्टेबिलिटी के लिए ऑप्टिमाइज़ेशन को भूल जाते हैं। कुछ समय में संकलित कोड वास्तविक कोड से अधिक पठनीय होते हैं।


0

आप स्ट्रिंग शाब्दिक उपयोग कर रहे हैं,

जब दो समान स्ट्रिंग शाब्दिक पकड़,

यह एक ही मेमोरी लोकेशन देता है, इसलिए यह एक ही पॉइंटर लोकेशन दिखाता है ।/

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