2015-11-03 9 views
5
सूचक बिंदु बनाने के लिए कैसे

मान लीजिए मैं एक सरणी में तीसरे तत्व के लिए एक uint8_t सूचक बिंदु है, {1, 2, 4, 5} तो *p 4. है मैं इसे कैसे बात करने के लिए प्राप्त कर सकते हैं 4 और 5 तक ताकि *p 45 हो। क्या यह भी संभव है? मैं वर्तमान में टाइपकास्टिंग कर रहा हूँ। यहां मैं क्या करता हूं उदा। यदि डेटा मेरी सरणी है {1, 2, 4, 5} और मैं 4 और 5.दो या अधिक लगातार कोशिकाओं

uint8_t dummyAddress = data[2]; 
dummyAddress = *((uint16_t*) dummyAddress); 
*p = *dummyAddress; 

मेरे समझ है कि पी अब 4 और 5 को इंगित करना चाहिए प्राप्त करना चाहते हैं, लेकिन मैं नहीं कर रहा हूँ। जब मैं दूसरी पंक्ति निष्पादित करता हूं तो इसके बजाय मुझे एक सीजी गलती मिलती है। पी uint64_t * const है। यह एक बाइट प्राप्त करने के लिए काम करता है, लेकिन दो बाइट्स पर एक ही तर्क लागू करते समय मुझे यह सही नहीं मिल रहा है।

+0

कृपया पूरा कोड दें (ऐरे घोषणा, उपयोग किए गए चर के प्रकार, ...)। –

+0

आपको उच्च चेतावनी स्तर के साथ संकलित करना चाहिए और कंपाइलर चेतावनियों को सुनना चाहिए। –

+1

अपने कोड में 'dummyAddress' एक सूचक –

उत्तर

4

आप ऐसा कर सकते हैं:

uint8_t data[] = { 1, 2, 4, 5 }; 
uint8_t *p8 = &data[2]; 
uint16_t u16 = *(uint16_t*)p8; 

फिर (uint16_t*)p8data[2] और data[3] को इंगित करेंगे। लेकिन आप आसानी से *(uint16_t*)p8 तक नहीं पहुंच सकते हैं। सबसे पहले ऐसा इसलिए है क्योंकि p8uint16_t सीमा पर गठबंधन नहीं किया जा सकता है। कुछ प्रोसेसर इस मामले में अपवाद का कारण बनते हैं। दूसरा, भले ही आप *(uint16_t*)p8 तक पहुंच सकें, आपको प्रोसेसर के बाइट ऑर्डर (बड़े एंडियन/छोटे एंडियन) के आधार पर अलग-अलग परिणाम मिल सकते हैं। आपको 0x0405 मिल सकता है या आपको 0x0504 मिल सकता है।

कृपया ध्यान दें कि आपके लाइन

dummyAddress = *((uint16_t*) dummyAddress); 

में आप पहली बार uint16_t के सूचक के रूप dummyAddress पुनर्व्याख्या कर रहे हैं और फिर इसे अपसंदर्भन, तो एक uint16_t लौटने और dummyAddress में इस भंडारण। यह स्पष्ट रूप से वह नहीं है जिसे आप करना चाहते थे। यदि यह वास्तव में संकलित करता है, तो कृपया उच्च चेतावनी स्तर के साथ संकलन करने पर विचार करें और प्रत्येक कंपाइलर चेतावनी पर नज़र डालें (और केवल इसे अनदेखा करें यदि आप इसे समझते हैं और सुनिश्चित हैं कि यह प्रोग्रामिंग त्रुटि नहीं है)।

बीटीडब्ल्यू, आप अपने प्रश्न में अनुरोध करते समय p जहां *p==45 प्राप्त करने में सक्षम नहीं होंगे।

इसके अलावा, जैसा मातृ एवं शिशु स्वास्थ्य ने कहा: What is the strict aliasing rule?

+0

डिफ़ॉल्ट रूप से यह थोड़ा endian में बाइट्स हड़पने के लिए लगता है, इसलिए * p 0x0504 है। अब अगर मैं इसे उलटना चाहता हूं तो * 0 0x405 पढ़ता है मैं इस बारे में उलझन में हूं कि इसके बारे में कैसे जाना है। मैंने देखा है कि लोग << ऑपरेटर का उपयोग करते हैं और 8 बार बिट्स को स्थानांतरित करते हैं या 256 से कई बार गुणा करते हैं? कोई स्पष्टीकरण कृपया – ponderingdev

+1

हां, आप इसे 'uint16_t a = ... जैसे स्थानांतरित करने के साथ कर सकते हैं; uint16_t बी = (एक >> 8) | (एक << 8) '। डेटा सरणी 'uint16_t b = ((uint16_t) डेटा पर भी बेहतर काम करने के लिए [2] << 8) | डेटा [3] '(या डेटा [2] और डेटा का आदान-प्रदान [3])। –

0

आप लिखना चाहिए:

uint_8_t *dummyAddress= &data[2]; 
uint_16_t *dummyAddress2= (uint16_t *) dummyAddress; 

uint_16_t p= *dummyAddress2; 

लेकिन ध्यान दें कि वजह से "endianness" करने के लिए आपके पास दो uint_8 की गलत क्रम में, यानी {data[3], data[2} के रूप में प्राप्त कर सकते हैं ।

+2

और यह अपरिभाषित व्यवहार है क्योंकि यह सख्त एलियासिंग नियम का उल्लंघन करता है। – mch

1

यदि मैं समझता हूं कि आप क्या कर रहे हैं, तो हाँ, आप uint16_t पर कास्ट करके दोनों बाइट्स तक पहुंच सकते हैं, लेकिन आप समस्याओं में बाइट्स को संग्रहीत करने के साथ-साथ उल्लंघन के तरीके के साथ समस्याओं (या अंतहीन मुद्दों) में भाग लेंगे सख्त अलियासिंग। यह शायद एक ऐसा जवाब देगा जो आपको संदेह नहीं था। उदाहरण के लिए:

#include <stdio.h> 
#include <stdint.h> 

int main (void) { 

    uint8_t array[] = {1,2,3,4}; 
    uint8_t *p = array + 2; 

    printf ("\n the uint8_t answer : %hhd\n", *p); 
    printf (" the uint16_t answer : %hd\n\n", *(uint16_t *)p); 

    printf ("**note: the will cast result in bytes 4, 3" 
      " (or (4 << 8 | 3) = 1027)\n\n"); 

    return 0; 
} 

आउटपुट

$ ./bin/cast_array 

the uint8_t answer : 3 
the uint16_t answer : 1027 

**note: the cast will result in bytes 4, 3 (or (4 << 8 | 3) = 1027) 

बाइट्स little endian क्रम में अपने सिस्टम पर स्मृति में जमा हो जाती है। तो जब आप uint16_t पर जाते हैं तो यह least significant, most significant बाइट्स खोजने की अपेक्षा करता है।कौन सा स्मृति में 34 साथ ऊपर के उदाहरण में, डाली वास्तविक क्रम 43 रूप 1027 बजाय (3 << 8) | 4 = 772 के एक मूल्य है, जिसके परिणामस्वरूप व्याख्या करेगा।

के रूप में बताया गया है, आप सख्त अलियासिंग जहां प्रकार छंटाई से संबंधित नियमों के उल्लंघन की जाएगी से char परिणाम अपरिभाषित व्यवहार में कुछ भी करने के लिए कास्टिंग द्वारा। इन सभी कार्यों के परिणाम हार्डवेयर और कंपाइलर निर्भर हैं और इन्हें सीखने के व्यायाम के अलावा किसी अन्य चीज़ के लिए उपयोग नहीं किया जाना चाहिए।

+0

'* (uint16_t *) पी 'अपरिभाषित व्यवहार का आह्वान करता है, क्योंकि यह सख्त एलियासिंग नियम का उल्लंघन करता है। – mch

+0

हां मैं टाइपिंग के बारे में एक नोट छोड़ दूंगा। –

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