2017-07-23 13 views
8

सी सी ++ के विपरीत संदर्भ वापस नहीं कर सकता है। क्या इसका मतलब यह है कि यदि आप A[i] तक पहुंचते हैं तो यह अभिव्यक्ति का मूल्यांकन करने में तत्व की प्रतिलिपि बनायेगा?क्या सी हर बार जब आप सरणी एक्सेस करते हैं तो तत्व कॉपी करते हैं?

उदाहरण है अगर रों की एक सरणी है के लिए, A[5]+=1; केवल अस्थायी प्रतिलिपि जब A[5] का मूल्यांकन बनाया, सी ++ के वेक्टर के विपरीत जो वास्तविक छठा तत्व में ही बढ़ेगी, जब भी वृद्धि करता है?

+14

'एक [5]' सरणी तत्व सीधे dereferences, कोई अस्थायी शामिल प्रतियां। – user0042

+0

'ए [5] + = 1' सरणी 'ए' के फिट शून्य-आधारित तत्व को बढ़ाता है। अगर ऐसा नहीं होता है, तो कंपाइलर में एक बग है। आप जो पूछ रहे हैं उसे अस्पष्ट करें। – EJP

+0

'ए [5] + = 1' 'ए [5] = ए [5] + 1' जैसा ही है, एक अनुकूलन कंपाइलर कुछ प्रतियां, यदि कोई हो, तो संभवतः व्यक्त किया जा सकता है मशीन भाषा। – nos

उत्तर

12

सी में एक 'लवल्यू' नामक एक अवधारणा है जो एक संदर्भ की तरह है। यह एक प्रकार नहीं है (प्रकार प्रणाली का हिस्सा नहीं है), लेकिन कुछ सी अभिव्यक्ति 'lvalues' हैं, और केवल ऐसे अभिव्यक्ति असाइनमेंट के बाएं ऑपरेंड (एक ऑप-असाइन सहित) या वृद्धि/कमी हो सकती है।

चूंकि सी में कोई ऑपरेटर ओवरलोडिंग नहीं है, इसलिए टाइप सिस्टम में भेद करने की कोई आवश्यकता नहीं है क्योंकि चीजों को समानता के रूप में घोषित करने की आवश्यकता नहीं है। सी ++ में ऑपरेटर ओवरलोडिंग जोड़ने की इच्छा थी जो ओवरलोडेड ऑपरेटरों के लिए रैवल्यू/लैवल्यू भेद स्पष्ट करने के लिए संदर्भ प्रकारों की शुरूआत की ओर ले जाती है।

5

यदि यह सत्य था, तो आप सभी को सरणी संशोधित करने में असमर्थ होंगे और अभिव्यक्ति A[5]+=1; का कोई प्रभाव नहीं होगा!

इसके विपरीत, जब आप किसी फ़ंक्शन पर स्केलर तर्क पास करते हैं, तो यह प्रतिलिपि की तरह व्यवहार करता है क्योंकि यह बदले में संशोधित नहीं होता है। लेकिन वास्तव में एक सूचक के रूप में पारित एक सरणी की प्रतिलिपि नहीं बनाई जाती है (जो असहनीय रूप से महंगी होगी) और वापसी पर अलग हो सकती है।

2

सी हमेशा एक तत्व जब A[i] साथ एक सरणी से पढ़ने, कि है, जब अभिव्यक्ति A[i] एक "rvalue" है प्रतियां। हालांकि, जब विचार लिखते हैं, सी 'lvalue "भाव है, जो अनिवार्य अभिव्यक्ति वाक्य रचना की एक सीमित सबसेट है कि एक काम के स्थल के रूप में प्रकट करने के लिए अनुमति दी जाती है कर रहे हैं की एक धारणा है:

X = Y 
*X = Y 
X[i] = Y 
X.n = Y 

इन मामलों में, "भाव" *X, X[i], और X.n वास्तव में करने के लिए मूल्यांकन नहीं मान-वे अभिव्यक्ति के रूप में एक ही वाक्य रचना है, सुविधा के लिए, लेकिन एक ही अर्थ विज्ञान। आप और अधिक की तरह कुछ के रूप में इन के बारे में सोच सकते हैं:

memcpy(&X, &Y, sizeof(Y)); 
memcpy(&*X, &Y, sizeof(Y)); 
memcpy(&X[i], &Y, sizeof(Y)); 
memcpy(&X.n, &Y, sizeof(Y)); 

या, वैकल्पिक रूप से, कई अलग काम ऑपरेटरों होने के रूप में सी के बारे में सोच:

_ = _ // direct assignment 
*_ = _ // indirect assignment 
_[_] = _ // special case of indirect assignment 
_._ = _ // special case of indirect assignment 

किसी भी तरह से, एक काम जैसे A[5] += 1A के छठे तत्व के मूल्य में वृद्धि होगी, जैसा कि आप उम्मीद करेंगे, जिसे आप इस तरह सत्यापित कर सकते हैं:

int A[1] = { 1 }; 
A[0] += 5; 
printf("%d\n", A[0]); // 6 
4

करता है एक [5] + = 1; केवल अस्थायी प्रतिलिपि जब मूल्यांकन कर एक [5]

सं A[5]+=1;A 6 तत्व 1 से वृद्धि का कारण होगा बनाया बढ़ाने के।

यह सीपीयू में एक रजिस्टर में A[5] की प्रतिलिपि बनाकर हासिल किया जा सकता है, इसे बढ़ाकर मूल्य वापस कॉपी कर सकता है। बात यह है कि 32-बिट EAX संचायक में DWORD PTR [rbp-28] ले जाता है के लिए A[5]+=1;

mov  eax, DWORD PTR [rbp-28] 
    add  eax, 1 
    mov  DWORD PTR [rbp-28], eax 

x86-64 कोडांतरक उत्पन्न जीसीसी,

int main(){ 
    int A[10]; 
    A[5]+=1; 
    return 0; 
} 

यहाँ यह करने के लिए 1 कहते हैं और यह बढ़ता रहता है:

यहाँ एक कार्यक्रम है एक ही जगह पर वापस।

DWORD PTR [rbp-28] स्टैक-फ्रेम (rbp) के सापेक्ष अपनी स्थिति से A के 6 वें तत्व की पहचान करता है।

संदर्भों के बारे में बिंदु एक लाल हेरिंग है। सी और सी ++ दोनों मशीन कोड (संभवतः असेंबलर के माध्यम से) के लिए संकलित कर रहे हैं। A[5]+=1; का अर्थ या संकलित कैसे किया जाता है, इस बारे में भाषाओं की अन्य विशेषताओं पर कोई प्रभाव नहीं पड़ता है।

0

नहीं, मैं सरणी सूचकांक सिर्फ एक सूचक है इसलिए पूरे सरणी के बजाय केवल एक स्थान पारित किया जाता है और वास्तविक स्मृति स्थान का मान प्रभावित होता है।

कोशिश निम्नलिखित कोड:

#include<stdio.h> 
void function(int[]); 
int main() 
{ 
    int a[] = {0,1,2,3,4,5,6,7,8,9}; 
    int i; 
    for(i = 0; i < 10; i++) 
     printf("%d, ",a[i]);  
    function(a); 
    printf("\n"); 
    for(i = 0; i < 10; i++) 
     printf("%d, ",a[i]); 
    return 0; 
} 

void function(int b[]) 
{ 
    int i; 
    for(i = 0; i < 10; i++) 
     b[i] *= 10; 
} 

OUTPUT

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

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