2013-09-05 2 views
13

निम्नलिखित अवलोकन उत्पन्न हुआ क्योंकि मैं this questionchar[] और char* अंतरों का पालन कर रहा था।char [] और char * टाइपिफ़ के रूप में अलग क्यों हैं, लेकिन कभी-कभी ... नहीं?

#include <iostream> 

typedef char ar[]; 
typedef char* pr; 
void f2(ar x, pr y) 
{ 
    std::cout << std::is_same<decltype(x), decltype(y)>::value << '\n'; 
    std::cout << std::is_same<ar, pr>::value << '\n'; 
} 

int main() 
{ 
    char data[] = "data"; 
    char *ptr = data; 
    f2(data,ptr); 
    return 0; 
} 

आउटपुट (एप्पल LLVM संस्करण 4.2 (बजना-425.0.28))

1 
0 

क्यों के रूप में विभिन्न प्रकार की रिपोर्ट के इन, लेकिन नहीं अलग decltype() रों करते हैं? मेरा संदेह यह है कि वे वास्तव में प्रकार उनके typedef घोषणाओं के कारण अलग हैं, लेकिन फिर समान प्रकार के रूप में चर के रूप में क्यों रिपोर्ट की जाती है?

+0

क्षय? (फ़ंक्शन पैरामीटर के रूप में) – dyp

+1

(मेरी टिप्पणी पर विस्तारित :) फ़ंक्शन के पैरामीटर प्रकार [dcl.fct]/5 के अनुसार "क्षय" हैं: "प्रत्येक पैरामीटर के प्रकार का निर्धारण करने के बाद, प्रकार के किसी पैरामीटर" सरणी " टी' "या" फंक्शन रिटर्निंग 'टी' "को क्रमशः' टी 'के सूचक" या "लौटने के लिए सूचक" क्रमशः समायोजित किया गया है। इसलिए 'decltype (x) 'है *' char' * के सूचक, * 'char' * के अज्ञात बाध्य की सरणी नहीं (' ar' के विपरीत)। – dyp

+0

@DyP मानक संदर्भ के लिए धन्यवाद, महोदय। – WhozCraig

उत्तर

20

सी ++ में, सी में, एक पैरामीटर जिसे सरणी प्रकार के रूप में घोषित किया गया है, (संकलन समय पर) सूचक प्रकार के होने के लिए समायोजित किया गया है, विशेष रूप से सरणी के तत्व प्रकार के लिए एक सूचक।

ऐसा होता है कि सरणी प्रकार सीधे या टाइपिफ़ के माध्यम से निर्दिष्ट किया गया है (याद रखें कि टाइपिफ़ एक नया प्रकार नहीं बनाता है, केवल मौजूदा प्रकार के लिए उपनाम)।

तो यह:

typedef char ar[]; 
typedef char* pr; 
void f2(ar x, pr y) 
{ 
    // ... 
} 

वास्तव में मतलब है:

void f2(char* x, char* y) 
{ 
    // ... 
} 

एक और नियम, भी C और C++ द्वारा साझा, कि सरणी प्रकार का एक अभिव्यक्ति सबसे में लेकिन सभी नहीं, है संदर्भ, अंतर्निहित ने को सरणी ऑब्जेक्ट के पहले तत्व के पॉइंटर में परिवर्तित किया। इसका मतलब है कि अगर आप एक सरणी वस्तु को परिभाषित:

char arr[10]; 

आपको लगता है कि ऑब्जेक्ट का नाम एक तर्क के रूप में एक समारोह है कि एक char* पैरामीटर (जो सीमा जानकारी खो देता है) लेता है करने के लिए उपयोग कर सकते हैं।

सी में, मामलों में जहां इस अंतर्निहित रूपांतरण नहीं होता हैं:

  1. जब सरणी अभिव्यक्ति sizeof (sizeof arr के संकार्य है एक के आकार सरणी के आकार, नहीं पैदावार सूचक);
  2. जब सरणी अभिव्यक्ति यूनरी & (&arr का ऑपरेंड है पॉइंटर-टू-एरे है, पॉइंटर-टू-पॉइंटर नहीं है); और
  3. जब सरणी अभिव्यक्ति एक स्ट्रिंग शब्दशः है जो सरणी प्रकार (char s[] = "hello";) को किसी सरणी के रूप में s प्रारंभ करने के लिए उपयोग की जाती है, सूचक के रूप में नहीं)।

इन मामलों (या अन्य मामलों है कि सी में होते हैं ++) में से कोई भी अपने कार्यक्रम में दिखाई देते हैं, तो आपकी कॉल तो:

f2(data,ptr); 

f2 के प्रकार char* के दो सूचक मूल्यों से गुजरता है।

f2 अंदर, पैरामीटर वस्तुओं x और y प्रकार char* के दोनों हैं, इसलिए std::is_same<decltype(x), decltype(y)>::value सच है।

लेकिन ar और pr प्रकार अलग हैं। ar एक अपूर्ण सरणी प्रकार char[] है, और pr सूचक प्रकार char* है।

जो आपके प्रोग्राम के आउटपुट को बताता है। अजीबता होती है क्योंकि पैरामीटर x, जिसे आपने सरणी प्रकार ar के साथ परिभाषित किया है, वास्तव में char* प्रकार है, जो pr जैसा ही प्रकार है।

+0

धन्यवाद, कीथ। यह बहुत अच्छी तरह से प्रस्तुत किया गया था, और सामान्य टिप्पणी से डाइप के मानक संदर्भ के साथ-साथ, स्पष्ट रूप से बताता है कि क्या देखा जा रहा है। बहुत ज्यादा अधिमूल्यित। – WhozCraig

2

सी परिवार पास-बाय-वैल्यू है, और सरणी का सी मान इसके पहले तत्व के लिए सूचक है। जब आप एक फ़ंक्शन के लिए एक सरणी घोषित करने वाले आइटम को पास करते हैं, तो वास्तव में क्या हो रहा है यह है कि पॉइंटर, और सी प्रोटोटाइप का व्यवहार करता है जैसे कि आपने इसे इस तरह घोषित किया है।

1

मैंने कोड बदल दिया ताकि हम देख सकें कि f2 को किस प्रकार कॉल करना है। कॉल से पहले चर अलग-अलग प्रकार के होते हैं। कॉल करने के बाद वे एक ही बन गए हैं

typedef char ar[]; 
typedef char* pr; 
void f2(ar x, pr y) 
{ 
    cout << is_same<decltype(x), decltype(y)>::value << '\n'; //same type 
} 

int main() 
{ 
    ar data = "data"; 
    pr ptr = data; 
    cout << is_same<decltype(data), decltype(ptr)>::value << '\n'; // different 
    f2(data,ptr); 
    return 0; 
} 

उत्पादन होता है जैसा कि @jthill, @Dyp और थॉम्पसन @keith का कहना है इस सरणी सूचक के खस्ताहाल के कारण है।

+1

समस्या का एक और "विज़ुअलाइजेशन": 'is_same ' और 'is_same ' 'f2' के अंदर (और निश्चित रूप से' is_same ') है। – dyp

+1

ओह, और कुछ दिलचस्प: 'is_same ' भी 'false' है (क्योंकि' ar' अपूर्ण है और [basic.types]/6 कहता है कि वे अलग हैं)। – dyp

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