সিতে একটি কাঠামোকে অন্য কাঠামো বরাদ্দ করুন


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;

এখন উভয় স্ট্রাইকটির পয়েন্টারগুলি মেমরির একই ব্লকের দিকে ইঙ্গিত করে - সংকলক তথ্যগুলিতে পয়েন্টটি অনুলিপি করে না। কোন স্ট্রাক্ট উদাহরণটি ডেটার মালিক তা এখন জানা মুশকিল। এই কারণেই সি ++ ব্যবহারকারী-নির্ধারণযোগ্য অ্যাসাইনমেন্ট অপারেটরগুলির ধারণাটি আবিষ্কার করেছিল - আপনি এই কেসটি পরিচালনা করতে নির্দিষ্ট কোড লিখতে পারেন।


1
আমি এটি আপ করেছি কারণ এটি পড়ার ফলে আমার নিজের উত্তরের ত্রুটি / বাদ দেওয়া অনুধাবন করা যায়।
ক্লিফোর্ড

1
+1 উল্লেখ করার জন্য যে আসলে কোনও অনুলিপি চলছে না।
টম ডাকারিং

14
কেন এটি স্প্যাম হিসাবে চিহ্নিত করা হয়েছিল? কেউ কি তাদের মাউসের উপর নিয়ন্ত্রণ হারিয়েছে?
জর্জি ফ্রিত্শে

@gf এবং স্পষ্টতই আপত্তিকরও!

2
@ রহমানিসব্যাক আননের উত্তরটি এই বিষয় সম্পর্কে বেশ স্পষ্ট: "সংকলক তথ্যকে নির্দেশিত প্রতিলিপি করে না "। 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
আপনি কি সর্বদা আমার জন্য কাজ করে বলে মনে হয় কোন পরিস্থিতিতে এটির ব্যর্থতা বিশদভাবে বর্ণনা করতে পারেন
AlphaGoku

15

এটি একটি সাধারণ অনুলিপি, ঠিক যেমনটি আপনি করতেন memcpy()(সত্যই, কিছু সংকলক আসলে সেই কোডটির জন্য একটি কল উত্পন্ন করে memcpy())। সি-তে কোনও "স্ট্রিং" নেই, কেবল একটি গুচ্ছের অক্ষরকে নির্দেশ করে। যদি আপনার উত্স কাঠামোতে এই জাতীয় পয়েন্টার থাকে তবে পয়েন্টারটি অনুলিপি হয়ে যায়, চরগুলি নিজেরাই নয়।


ঠিক আছে, তাই সংকলকটিmemcpy এখানে এটি অনুবাদ করে দেখুন: Godbolt.org/z/nPxqWc - তবে এখন যদি আমি অভিন্ন পয়েন্টারগুলি পাস করি aএবং bএবং *a = *bএটি একটি memcpyঅনির্ধারিত আচরণে অনুবাদ করা হয় কারণ memcpy"স্মৃতি অঞ্চলগুলি অবশ্যই ওভারল্যাপ করা উচিত নয়।" (ম্যান পৃষ্ঠা থেকে উদ্ধৃতি)। তাহলে কি সংকলকটি ব্যবহারের ক্ষেত্রে ভুল memcpyবা আমি এইরকম কোনও এসাইনমেন্ট লেখার ক্ষেত্রে ভুল করছি?
এক ব্যবহারকারী নয়

6

আপনি কি বাস্তব এবং কাল্পনিক অংশগুলির মতো জটিল সংখ্যার মতো "কমপ্লেক্স" বলতে চাচ্ছেন? এটি অসম্ভব বলে মনে হচ্ছে, সুতরাং যদি আপনি একটি উদাহরণ দিতে না চান কারণ "জটিল" এর অর্থ সি ভাষার ক্ষেত্রে নির্দিষ্ট কিছু নয়।

আপনি কাঠামোর সরাসরি স্মৃতি কপি পাবেন; আপনি যা চান তা কাঠামোর উপর নির্ভর করে কিনা। উদাহরণস্বরূপ যদি কাঠামোটিতে একটি পয়েন্টার থাকে, উভয় অনুলিপি একই ডেটাতে নির্দেশ করবে। এটি আপনি যা চান তা হতে পারে বা নাও হতে পারে; এটি আপনার প্রোগ্রাম ডিজাইনের নিচে।

একটি 'স্মার্ট' অনুলিপি (বা একটি 'গভীর' অনুলিপি) সম্পাদন করতে, অনুলিপিটি সম্পাদন করার জন্য আপনাকে কোনও ফাংশন প্রয়োগ করতে হবে। এটি অর্জন করা খুব কঠিন হতে পারে যদি কাঠামোতে নিজেই পয়েন্টার এবং কাঠামোতে পয়েন্টার থাকে এবং সম্ভবত এই জাতীয় কাঠামোর দিকে নির্দেশ করে (সম্ভবত এটি "জটিল" বলতে আপনি বোঝাতে চান) এবং এটি বজায় রাখা শক্ত হয়। সহজ সমাধানটি হ'ল সি ++ ব্যবহার করা এবং প্রতিটি কাঠামো বা শ্রেণীর জন্য কপির কনস্ট্রাক্টর এবং অ্যাসাইনমেন্ট অপারেটরগুলি প্রয়োগ করা, তারপরে প্রত্যেকে নিজের কপির শব্দার্থবিজ্ঞানের জন্য দায়ী হয়ে যায়, আপনি অ্যাসাইনমেন্ট সিনট্যাক্স ব্যবহার করতে পারেন এবং এটি আরও সহজে বজায় রাখা হয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.