2014-10-20 21 views
5

मैं उलझन में क्यों मेरे संकलक निम्नलिखित हालत में एक त्रुटि फेंक रहा है:सी - अभिव्यक्ति एक परिवर्तनीय lvalue होना चाहिए

void funcExample (void * p_Buf, uint16_t len) 
{ 
    uint16_t i; 

    for (i = 0; i < len; i++) { 
     otherFunc (((uint8_t *)p_Buf)++); //error = expression must be a modifiable lvalue 
    } 
} 

लेकिन अगर मैं otherFunc को पारित करने से पहले डाली, यह ठीक है क्योंकि कोई समस्या नहीं incrementing है एक गैर-शून्य सूचक:

void funcExample (void * p_Buf, uint16_t len) 
{ 
    uint16_t i; 
    uint8_t * p_Buf_8bit; 

    p_Buf_8bit = (uint8_t *) p_Buf; 

    for (i = 0; i < len; i++) { 
     otherFunc (p_Buf_8bit++); 
    } 
} 

एक बार कास्ट पॉइंटर को कास्ट करने के बाद बढ़ाया नहीं जा सकता है? क्या मैं यहाँ कुछ मौलिक याद कर रहा हूँ?

+0

समान नहीं है, लेकिन * बहुत * [** समान प्रश्न यहाँ **] (http://stackoverflow.com/questions/24002044/क्यों-कर सकते हैं-ए-नहीं करते हैं-गणित-ऑन-ए-कलाकारों के-एक-शून्य-सूचक)। – WhozCraig

उत्तर

5

कास्ट ऑपरेटरों: बजाय इसका उपयोग

6.5.4। पी 5 एक संश्लेषित प्रकार नाम द्वारा अभिव्यक्ति से पहले नामित प्रकार के अभिव्यक्ति के मान को परिवर्तित करता है। इस निर्माण को कास्ट कहा जाता है। 104) एक कास्ट जो निर्दिष्ट करता है कोई रूपांतरण किसी अभिव्यक्ति के प्रकार या मान पर कोई प्रभाव नहीं पड़ता है।

104) एक कास्ट एक लाभा उत्पन्न नहीं करता है। इस प्रकार, एक योग्य प्रकार के लिए एक डाली प्रकार

लेकिन एकल ऑपरेटर ++ की अयोग्य संस्करण के लिए एक डाली जैसा ही होता है एक lvalue के रूप में कहा गया है की आवश्यकता है:

6.5.3.1 । पी 1 उपसर्ग वृद्धि या कमी ऑपरेटर के संचालन परमाणु, योग्य, या अयोग्य वास्तविक या सूचक प्रकार, होगा और एक संशोधित अंतराल होगा।

इसलिए आप कर सकते हैं:

p_Buf = (uint8_t*)p_Buf + 1 ; 

कहाँ p_Buf lvalue है और (uint8_t*)p_Buf rvalue है।


मुझे बस ध्यान दें कि आपके दूसरे उदाहरण में आप डाली नहीं है (जैसा कि आपने कहा था), लेकिन आप एक uint8_t सूचक घोषणा करते हैं। फिर जब आप ++ पर इसका उपयोग करते हैं तो आप कोई भी कलाकार नहीं करते हैं (क्योंकि इसमें सही प्रकार है) और ऑपरेशन मान्य है।

+0

आप अपने 'शून्य' पॉइंटर को पॉइंटर के बजाय 'uint8_t' में परिवर्तित कर रहे हैं। – Seprum

+0

@ सेपरम नहीं मैं नहीं हूं। आपने एक पुराना संपादन देखा होगा। पृष्ठ ताज़ा करें। – 2501

+0

पहले ही संपादित किया गया है। – Seprum

0

एक कास्ट ऑपरेशन का परिणाम एक रैवल्यू है, न कि एक लालसा। ((uint8_t *)p_Buf)++ कानूनी सी कोड नहीं है।

1

void पॉइंटर C में बढ़ाना बुरा विचार है। अधिकांश कंपाइलर्स इसे संकलित करने की अनुमति भी नहीं देते हैं। ग में

p_Buf = (uint8_t*)p_Buf + 1; 
1

उत्तर @ 2501 पोस्ट उत्तर सही है, लेकिन यह समझ में नहीं आता है कि मानक को lvalue पोस्ट-वृद्धि के लिए क्यों आवश्यक है। मूल कारण यह है कि आपको इसके वृद्धि के लिए पोस्ट-वृद्धि के लिए lvalue (चर या स्मृति स्थान) की आवश्यकता है।

जब आप p_Buf को uint8_t* प्रकार पर डालते हैं, तो आपने रैवल्यू सी में बनाया है।सरल शब्दों में, रैल्यू क्षणिक मानों का प्रतिनिधित्व करता है जो चरों को आवंटित कार्यों को पारित किया जा सकता है। पोस्ट-वृद्धि मूल मूल्य देता है और उसके बाद वैरिएबल या मेमोरी लोकेशन को अपडेट करता है जहां मूल्य संग्रहीत किया जाता है, इसे बढ़ाता है। क्योंकि वे केवल अभिव्यक्ति की अवधि के लिए मौजूद हैं, रावल अपडेट नहीं किए जा सकते हैं, और बाद में वृद्धि उनके लिए संचालित नहीं हो सकती है। इस प्रकार

otherFunc (((uint8_t *)p_Buf)++); //error = expression must be a modifiable lvalue 

साथ समस्या यह है कि ((uint8_t *)pBuf) सिर्फ एक rvalue कोई वास्तविक भंडारण स्थान के साथ अभिव्यक्ति है। असल में, कास्ट का मतलब है कि आप केवल p_Buf के मान का उपयोग कर रहे हैं, और अब सीधे p_Buf का उपयोग नहीं कर रहे हैं।

दूसरी ओर, जब आप एक चर करने के लिए डाली आवंटित:

p_Buf_8bit = (uint8_t *) p_Buf; 

तो चर p_Buf_8bit एक lvalue है, जो एक चर या स्मृति स्थान का प्रतिनिधित्व करते है। इस के बाद वृद्धि हो सकता है सी में यह एक पूरी तरह से अच्छी तरह से गठित वक्तव्य:

otherFunc (p_Buf_8bit++); 
+0

अतिरिक्त स्पष्टीकरण के लिए धन्यवाद -> यह वास्तव में मदद करता है। मुद्दा कास्ट की अस्थायी/क्षणिक प्रकृति (रावलु बनाम लालू) है। धन्यवाद। – jaypee

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