2012-08-29 17 views
6

एक चीज जो हमेशा मुझे उलझन में डालती है, चरित्र सूचक। यह चार साल बाद है कि मैं फिर से सी में लूंगा।एक सूचक प्रारंभ करने के लिए क्या करता है?

उदाहरण के लिए उल्लिखित मामला लें। char पॉइंटर इस तरह से व्यवहार क्यों करता है? पॉइंटी की सामग्री को सीधे कैसे संबोधित किया जा सकता है जब यह कुछ भी इंगित करता है या यह पते के अलावा चार पॉइंटर स्टोर्स सामान की तरह है!

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
char* charPtr="I cant understand why"; 
int* intPtr=60; 


printf("%d\n", intPtr); //displays 60 
printf("%p\n", intPtr); // displays the hex value of 60 

printf("%s\n", charPtr); // displays the wh0le string 
printf("%p\n", charPtr); // displays the start address of the string 
return 0; 

}

अगला int सूचक, यह कैसे मान 60 स्वीकार कर सकते हैं और जहां यह संग्रहीत होता है?

चार पॉइंटर और मॉलोक को छोड़कर, मैंने सोचा कि सूचक का मूल विचार इंगित करने के लिए एक पता प्राप्त करना था!

क्यों इन मामलों, जबकि

int* intPtr=60; 

एक पते के बिना में चोरी (या 60 पते के रूप में लिया है

*intptr = 60 ; // should be setting the pointee's value to 60 
    intptr = 60 ; // sets the address 

फेंक संकलन त्रुटि करता है यदि ऐसा है तो क्यों यह नहीं स्वीकार्य नहीं है पूर्व मामले) पॉइंट के!

मुझे लगता है कि मुझे कुछ याद आ रही है लेकिन हे! अंदाज़ा लगाओ ? उन्होंने मुझे एसओ में खोजने के लिए कहा!

संपादित करें: चार सूचक द्वारा इंगित पते को एक इंट पॉइंटर पर इंगित करने से भी कोई त्रुटि नहीं होती है!

int8_t* intPtr= (int8_t*)0x80485c8 ; // works without casting too ! I guess addresses are acceptable. 

अपसंदर्भन यह पहली I स्ट्रिंग के लिए एक मूल्य के बराबर दे देंगे यह एक अच्छा अभ्यास .is या वहाँ इस तरह के एक पूर्णांक एक चार धारण कर सकते हैं के रूप में उनके बाइट सा आकार आवंटन बाहर छोड़ने यह करने के लिए किसी भी अन्य स्पष्टीकरण मौजूद है इसलिए.. ?

जैसा कि एचएमजेडी ने 'प्रारंभिक वाक्यविन्यास' को इंगित किया है समस्या है! मुझे अपना कोड लिखने में कोई समस्या नहीं है लेकिन किसी के कोड को संशोधित करते समय परेशानी उत्पन्न होती है!

+0

यह जानना वास्तव में मुश्किल है कि आप वास्तव में क्या पूछ रहे हैं। एक सूचक एक चर है जिसका मूल्य आमतौर पर किसी अन्य चर का पता होता है। –

+0

* मुझे लगता है कि मैं यहाँ कुछ याद कर रहा हूं * अच्छा सी प्रोग्रामिंग पुस्तक/ट्यूटोरियल, वास्तव में। आपने बहुत से पूछे जाने वाले प्रश्न पूछे। –

+0

@ डेविडस्वार्टज़ हां! यह भी मेरे लिए मूल विचार है :) लेकिन यहां क्या हो रहा है? – Borrito

उत्तर

4

सी में, एक स्ट्रिंग शाब्दिक की तरह "मैं नहीं समझ सकता क्यों" char की एक सरणी ऐसी है कि स्मृति कार्यक्रम के जीवनकाल में उपलब्ध है के रूप में संग्रहीत किया जाता है (सभी पतों हवा से बाहर खींच रहे हैं और

Item  Address  0x00 0x01 0x02 0x03 
-----  -------  ---- ---- ---- ---- 
"I..."  0x00080000  'I' ' ' 'c' 'a' 
      0x00008004  'n' ''' 't' ' ' 
      0x00008008  'u' 'n' 'd' 'e' 
      0x0000800C  'r' 's' 't' 'a' 
      0x00008010  'n' 'd' ' ' 'w' 
      0x00008014  'h' 'y' 0x00 0x?? 

स्ट्रिंग शाब्दिक भी एक सरणी अभिव्यक्ति के प्रकार के "T के एन-तत्व वाली सरणी" एक अभिव्यक्ति है, और अधिकांश संदर्भों में में परिवर्तित हो जाएगा: किसी भी विशिष्ट मंच या आर्किटेक्चर) दिखाने के लिए नहीं कर रहे हैं टाइप "T सूचक", और अपने मूल्य पहले ई का पता हो जाएगा सरणी के lement (अपवाद हैं जब सरणी अभिव्यक्ति sizeof या एकल & ऑपरेटरों की एक संकार्य है, या एक स्ट्रिंग शाब्दिक एक घोषणा में एक सरणी प्रारंभ करने में इस्तेमाल किया जा रहा है)।

तो जब आप लिखना

char* charPtr = "I can't understand why"; 

आप charPtr को स्ट्रिंग शाब्दिक की पता कॉपी कर रहे हैं:

Item  Address  0x00 0x01 0x02 0x03 
----  -------  ---- ---- ---- ---- 
charPtr  0xffbe4000  0x00 0x08 0x00 0x00 

ध्यान दें कि यदि घोषणा की गई थी

char str[] = "I can't understand why"; 

str होगा char काफी लंबी स्ट्रिंग धारण करने के लिए की एक सरणी के रूप में आवंटित किया गया है, और सामग्री स्ट्रिंग के कॉपी किया गया है | यह करने के लिए:

Item  Address  0x00 0x01 0x02 0x03 
-----  -------  ---- ---- ---- ---- 
str   0xffbe4000  'I' ' ' 'c' 'a' 
      0xffbe4004  'n' ''' 't' ' ' 
      0xffbe4008  'u' 'n' 'd' 'e' 
      0xffbe400C  'r' 's' 't' 'a' 
      0xffbe4010  'n' 'd' ' ' 'w' 
      0xffbe4014  'h' 'y' 0x00 0x?? 

जब आप लिखना

int* intPtr = 60; 

आप कर रहे हैं सूचक मूल्य 60 के साथ मूल्य, इसे 60:

Item  Address  0x00 0x01 0x02 0x03 
----  -------  ---- ---- ---- ---- 
intPtr  0xffbe4004  0x00 0x00 0x00 0x3C 
के साथ अज्ञात पूर्णांक को इंगित करने के लिए सेट नहीं करना

पता 60 सबसे अधिक मान्य पता नहीं है, इसलिए intPtr को अपमानित करने का प्रयास करने की संभावना अधिकतर अपरिभाषित व्यवहार की ओर ले जाती है।

आप की तरह

int x = 60; 
int *intPtr = &x; 

कुछ लिखा था तो आप इस तरह एक स्थिति होगा:

Item  Address  0x00 0x01 0x02 0x03 
----  -------  ---- ---- ---- ---- 
x   0xffbe4004  0x00 0x00 0x00 0x3C 
intPtr  0xffbe4008  0xff 0xbe 0x40 0x04 

इस मामले में, intPtr का मूल्य x का पता है।

अंत में, ध्यान दें कि प्रारंभिकरण और असाइनमेंट समान नहीं है।

T *x = value; 

x भिन्नता नहीं है और परिणाम के लिए value आवंटित; यह value को सीधे x पर असाइन करता है। value का प्रकार T * के रूप में माना जाता है। ध्यान दें कि आप

int *intPtr = 60; 
"कलाकारों के बिना पूर्णांक से सूचक बनाने" की तर्ज पर

पर चेतावनी मिल होना चाहिए।

6

जब हम कुछ भी इंगित करते हैं तो पॉइंटी की सामग्री को सीधे हम कैसे संबोधित कर सकते हैं या यह पते के अलावा चार पॉइंटर स्टोर्स सामान की तरह है!

I सोच भ्रम प्रारंभिक वाक्यविन्यास है। यह:

char* charPtr="I cant understand why"; 

charPtr को अस्वीकार नहीं करता है।

char* charPtr; 
charPtr = "I cant understand why"; 

दोनों कोड के टुकड़े स्ट्रिंग शाब्दिक "I cant understand why"charPtr के पते की दुकान: यह के बराबर है। एक सूचक का कोई dereferencing नहीं है जो कुछ भी होने के लिए इंगित करता है। किसी भी प्रकार का पॉइंटर चर, केवल एक पता स्टोर कर सकता है।

यह:

int* intPtr=60; 

भंडार intPtr में 60 के एक पते: कोई int असाइनमेंट या deferencing उत्पन्न कर रहा है। इस बिंदु पर int चर मौजूद है। कंपाइलर को इस लाइन पर एक चेतावनी उत्सर्जित करनी चाहिए थी। intPtr सम्मान करने के लिए कोई भी प्रयास सबसे अधिक संभावना एक दुर्घटना का कारण होगा।

+0

मुझे लगता है कि आप सही हैं! वह सोच रहा है कि "ए = बी;" का मतलब है "चर के मान को बी के मान पर सेट करें"। लेकिन इसका वास्तव में क्या अर्थ है "चर को इस तरह सेट करें कि इसका मान बी है"। यदि एक्स का मान 2 है, 'x = 3;' चर 'x' से 3 सेट करने का प्रयास करता है, तो यह 2 से 3 सेट करने का प्रयास नहीं करता है। (मूलभूत अवधारणा ओपी गुम है जो लालसा बनाम लालसा है।) –

+0

@ hmjd तो char सूचक इस पहलू में कम से कम अन्य सूचक से कुछ अलग है, है ना? आपने कहा कि int * intPtr = 60; intPtr में 60 पता एक स्टोर करता है, इसलिए यदि मैं एक मान्य पता डालता हूं और इसे अस्वीकार करता हूं, तो क्या मुझे इस प्रकार के मूल्य के बावजूद मूल्य मिलेगा? मुझे लगता है कि सवाल को अपडेट करना बेहतर होगा। – Borrito

+0

@ बॉरिटो, नहीं। यहां अंतर वह प्रारंभिक मूल्य है जिसे आप assiging कर रहे हैं। 'Char *' के लिए, आप एक मान्य पता असाइन कर रहे हैं। 'Int *' के लिए, आप नहीं हैं। यदि आप 'int i = 4; int * intPtr = & i; 'तब' intPtr' में 'i' का पता होगा और यह 'intPtr' को सम्मानित करने के लिए कानूनी होगा। – hmjd

1

आपका intPtr पूर्ण स्मृति पता 60 को इंगित करने के आरंभ नहीं हो जाता। यहां कोई बैकिंग स्टोर नहीं है।

जब से तुम सूचक ही अपसंदर्भन नहीं कर रहे हैं, तो आप कभी नहीं पता 60 जो शायद पर्यावरण के आधार पर अपने कार्यक्रम दुर्घटना होगा पढ़ने के लिए कोशिश कर रहे हैं।

इसके बजाय आप सूचकांक को printf में पास कर रहे हैं जो तर्क के रूप में बहुत कुछ लेता है और प्रारूप स्ट्रिंग में निर्दिष्ट मानों को व्याख्या करता है। आपके मामले में यह सूचक मूल्य के बजाय सूचक के पते की व्याख्या करेगा। पता 60 है जो प्रदर्शित होता है। था आप *intPtr इस्तेमाल किया बजाय यह शायद होता दुर्घटनाग्रस्त हो गया।

2

जब आप लिखें:

char* charPtr = "I can't understand why"; 

इसका मतलब है कि स्ट्रिंग के आधार का पता "मैं नहीं समझ सकता क्यों"

charPtr करने के लिए आवंटित किया जा रहा है क्योंकि स्ट्रिंग शाब्दिक भी करने के लिए एक सूचक है वह स्ट्रिंग

the concept of string stored in an char array

इसका मतलब है कि, charPtr में पूरी स्ट्रिंग के आधार का पता इस .अब संग्रहीत किया जा रहा है जो आप अपने कोड में किया है:

यह रूप में देखी जा सकती है।

char *charPtr="i cant understand why"; 

कि करने के लिए जोड़ा जा रहा है, अगर आप की तरह बयान प्रिंट:

printf("%c","i cant understand why"[0]);//prints i 
printf("%c","i cant understand why"[2]);//prints c 

इन दो printf की मेरी अवधारणाओं को सही ठहराने कि स्ट्रिंग "मैं नहीं कर सकते क्यों" खुद चार सरणी के लिए सूचक है, जिसमें स्ट्रिंग संग्रहित किया जा रहा है।

संबंधित मुद्दे