স্ব রেফারেন্সিয়াল কাঠামো সংজ্ঞা?


134

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

typedef struct Cell {
  int isParent;
  Cell child;
} Cell;

9
পিএস আসলে এটি "স্ট্রাক্ট সেল" কে "সেল" টাইপ করে (এটি একটি সাধারণ প্যাটার্ন)
ডেভিড জেড

তিনি সম্ভবত একটি সি ++ সংকলক ব্যবহার করছেন। সে যদি সত্যিই সি হয় তবে _বুল ব্যবহার করা উচিত
নবি

সত্যিকারের সি :-)
প্যাক্সিডিয়াবলো

2
কেন? সি 99 এর বুল হয়েছে - আপনার কেবল <stdbool.h> অন্তর্ভুক্ত করা দরকার
জোনাথন লেফলার

উত্তর:


184

স্পষ্টতই একটি ঘরে অন্য কোষ থাকতে পারে না কারণ এটি কখনও শেষ না হওয়া পুনরুক্তি হয়।

তবে একটি সেল অন্য কক্ষে একটি পয়েন্টার ধারণ করতে পারে।

typedef struct Cell {
  bool isParent;
  struct Cell* child;
} Cell;

7
@ cs01 না, Cellএখনও সুযোগ নেই।
ফ্রেডওভারফ্লো

1
এটা তোলে হবে জানার জন্য। পাইথন এটির অনুমতি দেয় এমনকি এমন একটি সামগ্রীর ক্রমিকায়নের অনুমতি দেয়। সি ++ কেন নয়?
noɥʇʎԀʎzɐɹƆ

1
আমি যখন দায়িত্ব অর্পণ Cell*করার চেষ্টা করি তখন আমি সতর্কতা পাই cell->child
টোমা জ্যাটো - মনিকা

3
@ noɥʇʎԀʎzɐɹƆ কারণ পাইথন পয়েন্টারগুলিকে দূরে রাখে যাতে আপনি সেগুলি লক্ষ্য না করেন। যেহেতু structসি তে মূলত কেবল তাদের সমস্ত মান একে অপরের পাশে সংরক্ষণ করা হয়, তাই আসলে নিজের মধ্যে কোনও কাঠামো সংরক্ষণ করা অসম্ভব (কারণ সেই স্ট্রাক্টটিতে অন্য একটি থাকতে হবে এবং এর ফলে স্মৃতি কাঠামো অসীম আকার ধারণ করে) ।
jazzpi

1
ব্যবহারের ব্যাখ্যার জন্য struct Cell, এই উত্তরটি দেখুন
wizzwizz4

26

সি তে, আপনি টাইপডিফটি উল্লেখ করতে পারবেন না যা আপনি কাঠামোর সাথে তৈরি করছেন। নিম্নলিখিত পরীক্ষার প্রোগ্রামের মতো আপনাকে কাঠামোর নাম ব্যবহার করতে হবে:

#include <stdio.h>
#include <stdlib.h>

typedef struct Cell {
  int cellSeq;
  struct Cell* next; /* 'tCell *next' will not work here */
} tCell;

int main(void) {
    int i;
    tCell *curr;
    tCell *first;
    tCell *last;

    /* Construct linked list, 100 down to 80. */

    first = malloc (sizeof (tCell));
    last = first;
    first->cellSeq = 100;
    first->next = NULL;
    for (i = 0; i < 20; i++) {
        curr = malloc (sizeof (tCell));
        curr->cellSeq = last->cellSeq - 1;
        curr->next = NULL;
        last->next = curr;
        last = curr;
    }

    /* Walk the list, printing sequence numbers. */

    curr = first;
    while (curr != NULL) {
        printf ("Sequence = %d\n", curr->cellSeq);
        curr = curr->next;
    }

    return 0;
}

যদিও এটি স্ট্যান্ডার্ডের তুলনায় এটি আরও অনেক জটিল, আপনি struct Cellএটি প্রথম typedefসংকেতটি সম্পর্কে জেনে কিন্তু tCellশেষ পংক্তির আগে না জেনে সংকলক হিসাবে ভাবতে পারেন :-) এইভাবে আমি সেই নিয়মটি মনে করি।


সি ++ সম্পর্কে কী আপনি দয়া করে সি ++ সম্পর্কিত উত্তরগুলি লিঙ্ক করতে পারেন
রিমালনফায়ার

@রিমিরো, প্রশ্নটি একটি সি ছিল। আপনি যদি C ++ বৈকল্পিকের উত্তর চান তবে আপনার এটি প্রশ্ন হিসাবে জিজ্ঞাসা করা উচিত ।
প্যাক্সিডিয়াবলো

16

তাত্ত্বিক দৃষ্টিকোণ থেকে, ভাষাগুলি কেবল স্ব-রেফারেন্সিয়াল কাঠামোকে সমর্থন করতে পারে স্ব-অন্তর্ভুক্ত কাঠামো নয়।


ব্যবহারিক দৃষ্টিকোণ থেকে 'স্ট্রাক্ট সেল' এর প্রকৃত ঘটনাটি কত বড় হবে?
মার্শ রে

26
বেশিরভাগ মেশিনে, চার বাইট নিজের থেকে বড়।
টনিক

13

এর চারপাশে একটি ধরণের উপায় রয়েছে:

struct Cell {
  bool isParent;
  struct Cell* child;
};

struct Cell;
typedef struct Cell Cell;

আপনি যদি এটির মতো ঘোষণা করেন তবে এটি সংস্থাপককে সঠিকভাবে বলেছে যে স্ট্রাক্ট সেল এবং প্লেইন-ওল-সেল একই। সুতরাং আপনি সাধারণের মতোই সেলটি ব্যবহার করতে পারেন। তবুও প্রাথমিক ঘোষণার অভ্যন্তরে স্ট্রাক্ট সেলটি ব্যবহার করতে হবে যদিও।


9
কেন struct Cell;আবার লিখলেন?
মাকজ

@ এমকেজেড কারণ টাইপডিফ সংজ্ঞা সংকলন করার সময় সংকলক দ্বারা কার্যকর করা হয়নি struct Cell
টাইলার ক্রম্পটন

2
@TylerCrompton যদি উপরের কোড ব্লকটিকে একটি সি সি উত্স ফাইলে রাখা হয়, তবে টাইপডেফকে "অতিরিক্ত সংযোজনকারী " সংকলক দ্বারা কার্যকর করা হয়েছে struct Cell;। তবে, যদি কোনও কারণে আপনি প্রথম দুটি লাইন দিয়ে স্ট্রাক্টটি সংজ্ঞায়িত করার আগে আপনি অন্তর্ভুক্ত করেন এমন একটি শিরোলেখ ফাইলটিতে শেষ দুটি লাইন রাখেন Cell, তবে অতিরিক্তটি struct Cell;নেসিসিরি।
yyny

এটি এমনকি সি 99 এর অধীন সংকলন করে না।
টোমা জ্যাটো - মনিকা

2
@ YYYOYonnY না, আপনি এখনও লিখতে পারেন typedef struct Cell Cell;এবং এটি Cellএকটি উপাধি তৈরি করবে struct Cell। সংকলকটি struct Cell { .... }আগে দেখেছে কিনা তাতে কিছু যায় আসে না ।
মেলপোমেন

8

আমি জানি এই পোস্টটি পুরানো, তবে আপনি যে প্রভাবটি সন্ধান করছেন তা পেতে আপনি নীচের চেষ্টা করতে পারেন:

#define TAKE_ADVANTAGE

/* Forward declaration of "struct Cell" as type Cell. */
typedef struct Cell Cell;

#ifdef TAKE_ADVANTAGE
/*
   Define Cell structure taking advantage of forward declaration.
*/
struct Cell
{
   int isParent;
   Cell *child;
};

#else

/*
   Or...you could define it as other posters have mentioned without taking
   advantage of the forward declaration.
*/
struct Cell
{
   int isParent;
   struct Cell *child;
};

#endif

/*
    Some code here...
*/

/* Use the Cell type. */
Cell newCell;

উপরের কোড খণ্ডে উল্লিখিত দুটি ক্ষেত্রে যে কোনও একটিতে আপনি আপনার সন্তানের সেল কাঠামোটিকে পয়েন্টার হিসাবে ঘোষণা করতে হবে। আপনি যদি তা না করেন তবে আপনি "ক্ষেত্রের 'সন্তানের' অসম্পূর্ণ প্রকারের" ত্রুটি পাবেন। কারণটি হ'ল "স্ট্রাক্ট সেল" সংকলকটি কখন ব্যবহৃত হবে কখন এটি বরাদ্দ করতে হবে তা জানতে সংজ্ঞায়িত করতে হবে।

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


3

টাইপএফের বেসিক সংজ্ঞাটি যেতে দেয়। টাইপডিফ ব্যবহার করে একটি উপাত্ত একটি বিদ্যমান ডাটা টাইপ সংজ্ঞায়িত করতে হয় এটি ব্যবহারকারী সংজ্ঞায়িত বা অন্তর্নির্মিত।

typedef <data_type> <alias>;

উদাহরণ স্বরূপ

typedef int scores;

scores team1 = 99;

পূর্বে সংজ্ঞায়িত করা হয়নি এমন একই ডেটা ধরণের সদস্যের কারণে এখানে বিভ্রান্তি স্ব-রেফারেন্সিয়াল কাঠামোর সাথে is সুতরাং স্ট্যান্ডার্ড উপায়ে আপনি আপনার কোডটি লিখতে পারেন: -

//View 1
typedef struct{ bool isParent; struct Cell* child;} Cell;

//View 2
typedef struct{
  bool isParent;
  struct Cell* child;
} Cell;

//Other Available ways, define stucture and create typedef
struct Cell {
  bool isParent;
  struct Cell* child;
};

typedef struct Cell Cell;

তবে শেষ বিকল্পটি কিছু অতিরিক্ত লাইন এবং শব্দগুলি বাড়িয়ে দেয় যা সাধারণত আমরা করতে চাই না (আমরা আপনাকে জানি এত অলস;))। সুতরাং ভিউ 2 পছন্দ করুন।


typedefসিনট্যাক্স সম্পর্কে আপনার ব্যাখ্যাটি ভুল (উদাহরণস্বরূপ বিবেচনা করুন typedef int (*foo)(void);)। আপনার ভিউ 1 এবং দেখুন 2 টি উদাহরণ কাজ করে না: এগুলি struct Cellএকটি অসম্পূর্ণ প্রকার তৈরি করে, তাই আপনি আসলে childআপনার কোডটিতে ব্যবহার করতে পারবেন না ।
মেলপোমেন

3

আর একটি সুবিধাজনক পদ্ধতি হ'ল কাঠামোটির সাথে কাঠামোটিকে পূর্ব-টাইপ করা উচিত:

//declare new type 'Node', as same as struct tag
typedef struct Node Node;
//struct with structure tag 'Node'
struct Node
{
int data;
//pointer to structure with custom type as same as struct tag
Node *nextNode;
};
//another pointer of custom type 'Node', same as struct tag
Node *node;

1

একটি স্ট্রাকচার যা নিজের একটি রেফারেন্স ধারণ করে। কোনও কাঠামোর মধ্যে এটির একটি সাধারণ ঘটনা যা লিঙ্ক তালিকার নোডকে বর্ণনা করে। প্রতিটি নোডের চেইনের পরবর্তী নোডের একটি রেফারেন্স প্রয়োজন।

struct node
{
       int data;
       struct node *next; // <-self reference
};

1

পূর্ববর্তী সমস্ত উত্তর দুর্দান্ত, আমি কেবল একটি কাঠামোর নিজস্ব ধরণের কোনও উদাহরণ থাকতে পারে না কেন তা সম্পর্কে একটি অন্তর্দৃষ্টি দেওয়ার চিন্তা করেছি (রেফারেন্স নয়)।

কাঠামোগুলি 'মান' ধরণের অর্থাত্ এগুলি প্রকৃত মান ধারণ করে এটি অত্যন্ত গুরুত্বপূর্ণ, সুতরাং আপনি যখন কোনও কাঠামো ঘোষণা করেন তখন সংকলকটিকে এটি নির্ধারণ করতে হবে যে এটির কোনও উদাহরণে কত মেমরি বরাদ্দ করতে হবে, সুতরাং এটি তার সমস্ত সদস্যদের মধ্যে গিয়ে যোগ করে স্ট্রাক্টের সমস্ত স্মৃতি অতিক্রম করার জন্য তাদের মেমরিটি আপ করুন তবে কম্পাইলারটি যদি একই কাঠামোর একটি উদাহরণ খুঁজে পেয়ে থাকে তবে এটি একটি প্যারাডক্স (অর্থাত্ মেমরি স্ট্রাক্ট এ কতটুকু গ্রহণ করে তা জানতে আপনাকে কতটা মেমোরি স্থির করতে হবে কাঠামো এ লাগে!)।

তবে রেফারেন্সের ধরনগুলি পৃথক, যদি স্ট্রাক্ট 'এ' এর নিজস্ব ধরণের একটি উল্লেখের জন্য 'রেফারেন্স' থাকে তবে যদিও আমরা জানি না যে এটির জন্য কত স্মৃতি বরাদ্দ করা হয়েছে, আমরা জানি মেমরির জন্য কত স্মৃতি বরাদ্দ করা হয়েছে ঠিকানা (অর্থাত্ রেফারেন্স)।

আছে HTH

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