C में एक स्ट्रक्चर को दूसरे में असाइन करें


146

क्या आप किसी संरचना का एक उदाहरण दूसरे को सौंप सकते हैं, जैसे:

struct Test t1;
struct Test t2;
t2 = t1;

मैंने इसे सरल संरचनाओं के लिए काम करते देखा है, क्या यह जटिल संरचनाओं के लिए काम करता है?
कंपाइलर को कैसे पता चलता है कि उनके प्रकार के आधार पर डेटा आइटम की प्रतिलिपि कैसे बनाई जाती है, यानी एक intऔर स्ट्रिंग के बीच अंतर करना ?

जवाबों:


151

हाँ यदि संरचना एक ही प्रकार की है। इसे मेमोरी कॉपी के रूप में सोचें।


72
ध्यान रखें कि कोई गहरी प्रति नहीं है, स्मृति की ओर इशारा नहीं किया गया है।
जॉर्ज शाओली

3
कंसीडर भी यहां एक मुद्दा है।
टिम पोस्ट

16
@ समाप्‍तता कोई अधिक समस्‍या नहीं है, क्योंकि यह बिल्‍ट में दिए गए असाइनमेंट के लिए है, जैसे कि पूर्णांक और डब्‍ल्‍यू - असाइनमेंट इन दोनों के लिए कोई परमाणु ऑपरेशन नहीं है।

2
ठीक है, अगर कॉपी बनाई गई है, तो क्या मैं बाद में मेमोरी को मुफ्त में मुफ्त कर सकता हूं ()?
बेटलिस्टा

5
@Betlista आप मेमोरी को मुफ्त में मुफ्त नहीं कर सकते () क्योंकि वे स्वचालित चर हैं: en.wikipedia.org/wiki/Automatic_variable
joshdoe

138

हां, स्ट्रक्चर्स के लिए असाइनमेंट समर्थित है। हालाँकि, समस्याएं हैं:

struct S {
   char * p;
};

struct S s1, s2;
s1.p = malloc(100);
s2 = s1;

अब दोनों स्ट्रक्चर्स के पॉइंटर्स मेमोरी के एक ही ब्लॉक की ओर इशारा करते हैं - कंपाइलर पॉइंटेड डेटा की कॉपी नहीं करता है। अब यह जानना मुश्किल है कि डेटा का कौन सा उदाहरण है। यही कारण है कि C ++ ने उपयोगकर्ता-निश्चित असाइनमेंट ऑपरेटरों की अवधारणा का आविष्कार किया - आप इस मामले को संभालने के लिए विशिष्ट कोड लिख सकते हैं।


1
मैंने इसे यूपीआई किया क्योंकि इसे पढ़ने से मुझे अपने उत्तर में त्रुटि / चूक का एहसास हुआ।
क्लिफोर्ड

1
+1 यह ध्यान देने के लिए कि वास्तव में कोई भी नकल नहीं चल रही है।
टॉम डेयरिंग

14
इसे स्पैम के रूप में क्यों चिह्नित किया गया था? क्या किसी ने अपने माउस पर नियंत्रण खो दिया है?
जॉर्ज फ्रिट्ज़

@ Gf और जाहिर तौर पर आक्रामक भी!

2
@rahmanisback इस विषय के बारे में एनॉन का उत्तर बिल्कुल स्पष्ट है: "संकलक इंगित किए गए डेटा की प्रतिलिपि नहीं बनाता है "। structस्वयं का डेटा स्पष्ट रूप से कॉपी किया गया है।
टोबियास

24

पहले इस उदाहरण को देखें:

एक साधारण सी प्रोग्राम के लिए सी कोड नीचे दिया गया है

struct Foo {
    char a;
    int b;
    double c;
    } foo1,foo2;

void foo_assign(void)
{
    foo1 = foo2;
}
int main(/*char *argv[],int argc*/)
{
    foo_assign();
return 0;
}

Foo_assign () के लिए समतुल्य ASM कोड है

00401050 <_foo_assign>:
  401050:   55                      push   %ebp
  401051:   89 e5                   mov    %esp,%ebp
  401053:   a1 20 20 40 00          mov    0x402020,%eax
  401058:   a3 30 20 40 00          mov    %eax,0x402030
  40105d:   a1 24 20 40 00          mov    0x402024,%eax
  401062:   a3 34 20 40 00          mov    %eax,0x402034
  401067:   a1 28 20 40 00          mov    0x402028,%eax
  40106c:   a3 38 20 40 00          mov    %eax,0x402038
  401071:   a1 2c 20 40 00          mov    0x40202c,%eax
  401076:   a3 3c 20 40 00          mov    %eax,0x40203c
  40107b:   5d                      pop    %ebp
  40107c:   c3                      ret    

जैसा कि आप देख सकते हैं कि असेंबली में "असाइन" निर्देश द्वारा केवल एक असाइनमेंट को प्रतिस्थापित किया जाता है, असाइनमेंट ऑपरेटर का मतलब केवल एक मेमोरी लोकेशन से दूसरे मेमोरी लोकेशन पर डेटा ले जाना है। असाइनमेंट केवल एक संरचना के तत्काल सदस्यों के लिए करेगा और जब आप किसी संरचना में कॉम्प्लेक्स डेटाटाइप करते हैं तो कॉपी करने में विफल होंगे। यहां कॉम्पलेक्स का मतलब है कि आपके पास सूचियों की ओर संकेत करने के लिए सरणी नहीं है।

एक संरचना के भीतर वर्णों की एक सरणी स्वयं ही अधिकांश संकलक पर काम नहीं करेगी, ऐसा इसलिए है क्योंकि असाइनमेंट बस डेटाटाइप को जटिल प्रकार के होने पर भी देखे बिना कॉपी करने की कोशिश करेगा।


2
क्या आप यह बता सकते हैं कि किन स्थितियों में यह विफल हो जाएगा क्योंकि यह हमेशा मेरे लिए काम करती है
अल्फा न्यू

15

यह एक सरल प्रतिलिपि है, जैसे आप memcpy()(वास्तव में, कुछ संकलक वास्तव में memcpy()उस कोड के लिए कॉल का उत्पादन करते हैं )। सी में कोई "स्ट्रिंग" नहीं है, केवल एक झुंड को एक संकेत देता है। अगर आपके सोर्स स्ट्रक्चर में ऐसा पॉइंटर है, तो पॉइंटर कॉपी हो जाता है, न कि चार्ट्स।


ठीक है, तो संकलक को यह तब्दील हो memcpy, यहाँ देखें: godbolt.org/z/nPxqWc - लेकिन अब अगर मैं समान संकेत पारित aऔर b, और *a = *bएक करने के लिए अनुवाद किया है memcpyअपरिभाषित व्यवहार है कि, क्योंकि के लिए memcpy"स्मृति क्षेत्रों नहीं ओवरलैप चाहिए।" (मैन पेज से उद्धृत)। तो संकलक का उपयोग करने में गलत है memcpyया क्या मैं इस तरह के असाइनमेंट को लिखने में गलत हूं?
उपयोगकर्ता

6

क्या आप वास्तविक और काल्पनिक भागों के साथ जटिल संख्या में "कॉम्प्लेक्स" का मतलब है? यह संभव नहीं लगता है, इसलिए यदि आपको "कॉम्प्लेक्स" का उदाहरण नहीं देना है तो इसका मतलब है कि सी भाषा के संदर्भ में कुछ खास नहीं है।

आपको संरचना की सीधी मेमोरी कॉपी मिल जाएगी; क्या आप जो चाहते हैं वह संरचना पर निर्भर करता है। उदाहरण के लिए यदि संरचना में एक सूचक होता है, तो दोनों प्रतियां एक ही डेटा को इंगित करेंगी। यह वही हो सकता है या नहीं हो सकता है जो आप चाहते हैं; यह आपके प्रोग्राम डिज़ाइन के लिए है।

'स्मार्ट' कॉपी (या 'डीप') कॉपी करने के लिए, आपको कॉपी को निष्पादित करने के लिए एक फंक्शन लागू करना होगा। यह प्राप्त करना बहुत मुश्किल हो सकता है यदि संरचना में स्वयं पॉइंटर्स और संरचनाएं होती हैं जिसमें पॉइंटर्स भी होते हैं, और शायद ऐसे संरचनाओं के लिए पॉइंटर्स (शायद यह है कि "जटिल" से आपका क्या मतलब है), और इसे बनाए रखना कठिन है। सरल समाधान यह है कि C ++ का उपयोग करें और प्रत्येक संरचना या वर्ग के लिए कॉपी कंस्ट्रक्टर और असाइनमेंट ऑपरेटरों को लागू करें, फिर हर एक अपने स्वयं के कॉपी शब्दार्थ के लिए जिम्मेदार हो जाता है, आप असाइनमेंट सिंटैक्स का उपयोग कर सकते हैं, और यह अधिक आसानी से बनाए रखा जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.