5

मैं निम्नलिखित कोड अपरिभाषित व्यवहार का आह्वान है कि क्या यह निर्धारित करने के कोशिश कर रहा हूँ:पुनर्व्याख्या के माध्यम से गलत संदर्भ बनाना डाली

#include <iostream> 

class A; 

void f(A& f) 
{ 
    char* x = reinterpret_cast<char*>(&f); 
    for (int i = 0; i < 5; ++i) 
    std::cout << x[i]; 
} 

int main(int argc, char** argue) 
{ 
    A* a = reinterpret_cast<A*>(new char[5]) 
    f(*a); 
} 

मेरे समझ है कि करने के लिए और char* से reinterpret_cast रों शिकायत क्योंकि मानक परमिट char और साथ aliasing हैं unsigned char संकेत (जोर मेरा):

तो एक कार्यक्रम othe के एक lvalue के माध्यम से एक वस्तु की संग्रहीत मूल्य का उपयोग करने का प्रयास निम्नलिखित प्रकार के व्यवहार अपरिभाषित है में से एक से r:

  • वस्तु के गतिशील प्रकार,
  • वस्तु के गतिशील प्रकार का एक सीवी योग्य संस्करण,
  • एक प्रकार है कि हस्ताक्षर किए या ऑब्जेक्ट के गतिशील प्रकार से संबंधित हस्ताक्षरित प्रकार,
  • ऑब्जेक्ट के गतिशील प्रकार के सीवी-योग्य संस्करण के साथ हस्ताक्षरित या हस्ताक्षरित प्रकार का एक प्रकार,
  • एक समेकित या संघ प्रकार जिसमें एक शामिल है उपरोक्त प्रकार के सदस्यों के बीच (सहित, पुनरावर्ती, एक subaggregate या निहित संघ) के एक सदस्य,
  • एक प्रकार है कि एक (संभवतः सीवी-योग्य) वस्तु के गतिशील प्रकार के आधार वर्ग प्रकार है,
  • एक char या unsigned char प्रकार।

हालांकि, मुझे यकीन है कि f(*a) अमान्य सूचक के लिए एक A& संदर्भ बनाकर अपरिभाषित व्यवहार का आह्वान है कि क्या नहीं कर रहा हूँ। निर्णायक कारक सी ++ मानक के संदर्भ में "पहुंचने का प्रयास" शब्दकोष का अर्थ है।

मेरे अंतर्ज्ञान करता है कि नहीं, एक पहुँच गठन के बाद से एक पहुँच A की आवश्यकता होगी में परिभाषित किया जा करने के लिए (यह घोषित किया जाता है, लेकिन इस उदाहरण में परिभाषित नहीं है)। दुर्भाग्यवश, मुझे सी ++ मानक में "एक्सेस" की ठोस परिभाषा नहीं मिल रही है:

क्या f(*a) अपरिभाषित व्यवहार का आह्वान करता है? सी ++ मानक में "पहुंच" का गठन क्या होता है?

मैं समझता हूं कि, जवाब के बावजूद, उत्पादन कोड में इस व्यवहार पर भरोसा करना एक बुरा विचार है। मैं इस प्रश्न को मुख्य रूप से भाषा की मेरी समझ में सुधार करने की इच्छा से पूछ रहा हूं।

[संपादित करें] @ सर्गेय ने मानक के इस खंड का हवाला दिया। मैं इसे यहाँ आसान संदर्भ (जोर मेरा) के लिए शामिल किया है:

5.3.1/1 [expr.unary.op]

एकल * ऑपरेटर अविवेक करता है: अभिव्यक्ति के लिए जो इसे लागू किया गया है किसी ऑब्जेक्ट प्रकार के लिए पॉइंटर, या किसी फ़ंक्शन प्रकार के पॉइंटर और परिणाम ऑब्जेक्ट या फ़ंक्शन का संदर्भ देने वाला एक लवल्यू है जिसमें अभिव्यक्ति बिंदुएं होती हैं।यदि अभिव्यक्ति का प्रकार "T पर सूचक है," परिणाम का प्रकार "T" है। [नोट: एक अपूर्ण प्रकार (सीवी शून्य के अलावा) के सूचक के माध्यम से संकेत मान्य है। इस प्रकार प्राप्त किया गया लाभा सीमित तरीकों से उपयोग किया जा सकता है (उदाहरण के लिए संदर्भ शुरू करने के लिए); यह अंतराल एक प्रसार में परिवर्तित नहीं किया जाना चाहिए, 4.1 देखें। - अंत टिप्पणी]

4,1 के संदर्भ ट्रेसिंग, हम पाते हैं:

4,1/1 [conv.lval]

एक गैर समारोह का एक glvalue (3.10) , गैर-सरणी प्रकार T को एक प्रसार में परिवर्तित किया जा सकता है। यदि T एक अधूरा प्रकार है, तो एक प्रोग्राम जो इस रूपांतरण की आवश्यकता है, खराब है। यदि टी एक गैर-वर्ग प्रकार है, तो प्रक्षेपण का प्रकार T का सीवी-अयोग्य संस्करण है। अन्यथा, प्रक्षेपण का प्रकार T है।

एक lvalue करने वाली rvalue रूपांतरण एक अभिव्यक्ति e को लागू किया जाता है, और या तो:

  • e संभावित मूल्यांकन नहीं किया जाता है, या
  • एक के मूल्यांकन में की e परिणाम मूल्यांकन e के संभावित परिणामों के सेट के सदस्य, और ex एक वेरिएबल x का नाम है जो ex (3.2)
  • द्वारा odr-used नहीं है

में निहित मान संदर्भित ऑब्जेक्ट तक नहीं पहुंचा है।

मुझे लगता है कि हमारा उत्तर *a दूसरे बुलेट बिंदु को संतुष्ट करता है या नहीं। मुझे उस स्थिति को पार्स करने में परेशानी हो रही है, इसलिए मुझे यकीन नहीं है।

+0

'ए' का संरेखण क्या है? – curiousguy

उत्तर

3

char* x = reinterpret_cast<char*>(&f); मान्य है। या, अधिक विशेष रूप से, x के माध्यम से पहुंच की अनुमति है - कास्ट स्वयं हमेशा मान्य है।

A* a = reinterpret_cast<A*>(new char[5]) मान्य नहीं है - या, सटीक होने के लिए, a के माध्यम से पहुंच अपरिभाषित व्यवहार को ट्रिगर करेगा।

इसका कारण यह है कि char* के माध्यम से ऑब्जेक्ट तक पहुंचना ठीक है, तो यादृच्छिक वस्तु के माध्यम से वर्णों की सरणी का उपयोग करना ठीक नहीं है। मानक पहले की अनुमति देता है, लेकिन दूसरा नहीं।

या, आम आदमी मामले में, आप एक type*char* के माध्यम से उर्फ ​​सकते हैं, लेकिन आप उर्फ ​​type* के माध्यम से char* नहीं कर सकता।

संपादित

मैं सिर्फ मैं सीधा सवाल का जवाब नहीं थे ("क्या गठन" पहुँच "C++ मानक")। जाहिर है, मानक एक्सेस (कम से कम, मैं औपचारिक परिभाषा नहीं ढूंढ पा रहा था) को परिभाषित नहीं करता है, लेकिन पॉइंटर को संदर्भित करने के लिए आमतौर पर पहुंच के लिए अर्हता प्राप्त करने के लिए समझा जाता है।

+0

मैं मानता हूं कि "ए 'के माध्यम से पहुंच अपरिभाषित व्यवहार को ट्रिगर करेगा," लेकिन (जैसा कि आप उल्लेख करते हैं),' ए * ए = reinterpret_cast (नया char [5]) 'पहुंच नहीं हो सकता है। दोबारा, जवाब "पहुंच" का गठन करने के लिए नीचे आता है। क्या * पॉइंटर डिफरेंस * या * एक लेल्यू * में रूपांतरण है (मुझे टाइप गलत हो रहा है) "एक्सेस"? –

+0

'ए * ए = ... 'एक पहुंच नहीं है। लेकिन एक सूचक को संदर्भित करना एक पहुंच है। – SergeyA

+0

पैडेंटिक होने के लिए खेद है, लेकिन * क्यों नहीं *? यह मुझे स्पष्ट नहीं है कि क्यों 'ए और बी = * ए' मूल रूप से 'ए * बी = ए' की तुलना में किसी भी पहुंच का है। उन बयानों में से कोई भी 'ए' परिभाषित करने की आवश्यकता नहीं है; केवल घोषित क्या मानक में कुछ भी है जो इस व्याख्या पर संकेत देता है? –

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