সিলে একাধিক ফাইল ব্যবহার করতে হয় এমন একটি শিরোনামে এমন কাঠামো কীভাবে ঘোষণা করবেন?


115

যদি আমার কাছে স্ট্রাক্ট সহ একটি সোর্স কোড ফাইল থাকে:

struct a { 
    int i;
    struct b {
        int j;
    }
};

এই স্ট্রাক্টটি অন্য কোনও ফাইলে (যেমন func.c) কীভাবে ব্যবহার করা যেতে পারে ?

আমি কি একটি নতুন শিরোনাম ফাইল তৈরি করব, সেখানে স্ট্রাক্ট ঘোষণা করব এবং সেই শিরোনামটি অন্তর্ভুক্ত করব func.c?

বা আমি একটি শিরোনাম ফাইলে সম্পূর্ণ কাঠামো সংজ্ঞায়িত করা এবং এটি উভয় source.cএবং অন্তর্ভুক্ত করা উচিত func.c? externউভয় ফাইলে স্ট্রাক্ট কীভাবে ঘোষণা করা যায়?

আমার typedefএটা করা উচিত? যদি তাই হয়, কিভাবে?


নোট করুন যে কাঠামোর সংজ্ঞাটি বৈধ নয় সি ন্যূনতম জন্য কাছাকাছি বন্ধনী পরে একটি সেমিকোলন হওয়া উচিত struct b, তবে তারপরে আপনার কাঠামোটি aএমন একটি প্রকার ঘোষণা করে যা অব্যবহৃত রয়েছে (আপনার সম্ভবত কোনও সদস্যের নাম সংজ্ঞায়িত করা উচিত, সম্ভবত kঅভ্যন্তরের নিকট বন্ধনী পরে এবং সেমিকোলনের আগে
জোনাথন লেফলার

উত্তর:


140

যদি এই কাঠামোটি অন্য কোনও ফাইল ফানক.সি দ্বারা ব্যবহার করতে হয় তবে এটি কীভাবে করবেন?

যখন কোনও ফাইলে কোনও টাইপ ব্যবহৃত হয় (অর্থাত্ func.c ফাইল), এটি অবশ্যই দৃশ্যমান হবে। এটি করার সবচেয়ে খারাপ উপায় হ'ল প্রতিটি উত্স ফাইলটিতে এটির অনুলিপি করা উচিত।

সঠিক উপায়ে এটি একটি শিরোনাম ফাইলে রাখছে এবং যখনই প্রয়োজন হবে এই হেডার ফাইলটি অন্তর্ভুক্ত করবে।

আমরা কি নতুন হেডার ফাইলটি খুলব এবং সেখানে কাঠামোটি ঘোষনা করব এবং সেই শিরোনামটিকে ফানক সিটিতে অন্তর্ভুক্ত করব?

এটি আমার আরও পছন্দ মতো সমাধান, কারণ এটি কোডটিকে অত্যন্ত মডুলার করে। আমি আপনার স্ট্রাক্ট হিসাবে কোড করব:

#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME

struct a
{ 
    int i;
    struct b
    {
        int j;
    }
};

#endif

আমি এই কাঠামোটি একই শিরোনামটিতে ব্যবহার করব (যে ফাংশনটি "শব্দ" এর "ইন্টারফেসের" অংশ))

এবং সাধারণত, আমি কাঠামোর নামের পরে ফাইলটির নাম রাখতে পারতাম এবং আবার সেই নামটি ব্যবহার করে শিরোনাম রক্ষীদের সংজ্ঞা দেওয়া পছন্দ করতে বেছে নিতে পারি।

আপনার যদি স্ট্রাক্টের পয়েন্টার ব্যবহার করে কোনও ফাংশন ডিক্লেয়ার করতে হয় তবে আপনার সম্পূর্ণ স্ট্রাক্ট সংজ্ঞা প্রয়োজন হবে না। একটি সহজ ফরোয়ার্ড ঘোষণা যেমন:

struct a ;

যথেষ্ট হবে, এবং এটি সংমিশ্রণ হ্রাস।

বা আমরা শিরোনাম ফাইলে মোট কাঠামোটি সংজ্ঞায়িত করতে পারি এবং এটি Source.c এবং func.c উভয়ই অন্তর্ভুক্ত করতে পারি?

এটি অন্য উপায়, কিছুটা সহজ, তবে কম মডুলার: কিছু কোড কেবলমাত্র আপনার কাঠামোর জন্য প্রয়োজন এখনও সব ধরণের অন্তর্ভুক্ত থাকতে হবে।

সি ++ এ, এটি আকর্ষণীয় জটিলতার দিকে নিয়ে যেতে পারে, তবে এটি বিষয়বস্তু থেকে বাইরে (কোনও সি ++ ট্যাগ নেই), তাই আমি বিশদভাবে বলব না।

তারপরে কীভাবে উভয় ফাইলের মধ্যে সেই কাঠামোটিকে বাহ্যিক হিসাবে ঘোষণা করবেন। ?

আমি সম্ভবত পয়েন্টটি দেখতে ব্যর্থ, তবে গ্রেগ হিউগিলের পোস্টটিতে খুব ভাল উত্তর রয়েছে যে কোনও শিরোনামে এমন একটি কাঠামো কীভাবে ঘোষণা করতে হয় যা সি-তে একাধিক ফাইল ব্যবহার করতে হয়?

আমরা কীভাবে টাইপ করব?

  • আপনি যদি সি ++ ব্যবহার করেন তবে করবেন না।
  • আপনি যদি সি ব্যবহার করছেন, আপনার উচিত।

সি স্ট্রাক্ট পরিচালনা করা ব্যথার কারণ হতে পারে: আপনার স্ট্রাক কীওয়ার্ডটি যে কোনও জায়গায় ব্যবহার করা উচিত তা আপনাকে ঘোষণা করতে হবে:

struct MyStruct ; /* Forward declaration */

struct MyStruct
{
   /* etc. */
} ;

void doSomething(struct MyStruct * p) /* parameter */
{
   struct MyStruct a ; /* variable */
   /* etc */
}

যদিও কোনও টাইপেইফ আপনাকে স্ট্রাক কীওয়ার্ড ছাড়াই এটি লিখতে সক্ষম করবে।

struct MyStructTag ; /* Forward declaration */

typedef struct MyStructTag
{
   /* etc. */
} MyStruct ;

void doSomething(MyStruct * p) /* parameter */
{
   MyStruct a ; /* variable */
   /* etc */
}

এটি গুরুত্বপূর্ণ যে আপনি এখনও কাঠামোর জন্য একটি নাম রাখবেন। লেখা:

typedef struct
{
   /* etc. */
} MyStruct ;

কেবলমাত্র একটি টাইপএফ-এড নামের সাথে একটি বেনামি কাঠামো তৈরি করবে এবং আপনি এটিকে ফরোয়ার্ড-ডিক্লেয়ার করতে সক্ষম হবেন না। সুতরাং নিম্নলিখিত বিন্যাসে রাখুন:

typedef struct MyStructTag
{
   /* etc. */
} MyStruct ;

সুতরাং, আপনি স্ট্রাক কীওয়ার্ড যুক্ত করা এড়াতে চান যেখানেই মাইস্ট্রাক্ট ব্যবহার করতে সক্ষম হবেন এবং যখন কোনও টাইপডেফ কাজ না করে তখনই মাইস্ট্রাকট্যাগ ব্যবহার করবেন (যেমন এগিয়ে ঘোষণা)

সম্পাদনা:

জনাথন লেফলার যথাযথভাবে মন্তব্য করেছেন, C99 কাঠামো ঘোষণার বিষয়ে ভুল ধারণা সংশোধন করেছেন ।

2018-06-01 সম্পাদনা করুন:

ক্রেগ বার্নস তার মন্তব্যে আমাদের স্মরণ করিয়ে দিয়েছেন যে আপনার স্ট্রাক্ট "ট্যাগ" নাম এবং এর "টাইপডিফ" নামের আলাদা আলাদা নাম রাখার দরকার নেই, যেমন আমি পরিষ্কার করার জন্য উপরে করেছি।

প্রকৃতপক্ষে, উপরের কোডটি ভালভাবে লেখা যেতে পারে:

typedef struct MyStruct
{
   /* etc. */
} MyStruct ;

আইআইআরসি, এটি সি এর সাথে সামঞ্জস্যপূর্ণ রাখার জন্য দৃশ্যের পিছনে, সহজ সরল কাঠামোর ঘোষণার সাথে এটি করে:

// C++ explicit declaration by the user
struct MyStruct
{
   /* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;

সি তে ফিরে, আমি উভয় ব্যবহার দেখেছি (পৃথক নাম এবং একই নাম), এবং আমার জানা কোনও ত্রুটি নেই, সুতরাং একই নাম ব্যবহার করা যদি আপনি স্ট্রাক্ট এবং অন্যান্য চিহ্নগুলির জন্য সি পৃথক "নেমস্পেস" ব্যবহার না করেন তবে পড়া সহজ করে তোলে if ।


2
আপনি কি "99 আপনি C99 ব্যবহার করছেন," মন্তব্য করবেন না এমন C99 স্ট্যান্ডার্ডের সেই অংশটি সম্পর্কে মন্তব্য করতে বা নির্দেশ করতে পারেন?
জোনাথন লেফলার

তুমি ঠিক বলছো. আমি সম্প্রতি একটি সি 99 পরীক্ষা করেছি এবং অবাক হয়ে দেখেছি যে আমার আনটাইপিডেড স্ট্রাক্টটি যখন সি ++ উপায় ব্যবহার করা হয়নি তখন তা স্বীকৃত ছিল না। আমি সংকলক বিকল্পগুলির জন্য অনুসন্ধান করেছি এবং তারপরে, সমস্ত স্ট্যান্ডার্ড ডকুমেন্টগুলিতে আমি হাত রাখতে পারি, তবে এমন কোনও কিছুই খুঁজে
পেল

2
... যাইহোক, মন্তব্যের জন্য ধন্যবাদ। আমি এখনই এটি সংশোধন করেছি।
পেরেসেবল

structট্যাগ এবং নামের জন্য আলাদা আলাদা নাম ব্যবহার করার দরকার নেই typedef। সি structট্যাগগুলির জন্য পৃথক নেমস্পেস ব্যবহার করে , তাই আপনি MyStructউভয়ের জন্যই ব্যবহার করতে পারেন ।
ক্রেগ বার্নস

1
@ ক্রেইগবার্নস আপনি ঠিক বলেছেন তবে আমি কোডটি পড়ে এটি পরিষ্কার হতে চেয়েছিলাম। আমি যদি একই নামটি দিয়ে থাকি তবে এটি একই "ঘোষণায়" দু'বার "নাম লেখার প্রয়োজনে সি নবীনদের বিভ্রান্ত করতে পারে I আমি আপনার মন্তব্যের উল্লেখ করে একটি নোট যুক্ত করব। ধন্যবাদ!
পেরেেসবাল

34

একাধিক উত্স ফাইল জুড়ে যে কাঠামো সংজ্ঞাটি ব্যবহার করা উচিত তার জন্য অবশ্যই এটি অবশ্যই একটি শিরোনাম ফাইলে রাখা উচিত। তারপরে কাঠামোর প্রয়োজন হয় এমন কোনও উত্স ফাইলে সেই শিরোলেখ ফাইলটি অন্তর্ভুক্ত করুন।

externঘোষণা গঠন সংজ্ঞা ব্যবহার করা হয় না, কিন্তু এর পরিবর্তে পরিবর্তনশীল ঘোষণা জন্য ব্যবহার করা হয় (যে, একটি কাঠামো ধরনের সঙ্গে কিছু ডেটা মান আপনি সংজ্ঞায়িত করেছেন যে)। আপনি যদি একাধিক উত্স ফাইল জুড়ে একই চলকটি ব্যবহার করতে চান তবে এটি externশিরোনামের মতো ফাইল হিসাবে ঘোষণা করুন:

extern struct a myAValue;

তারপরে, একটি উত্স ফাইলে আসল ভেরিয়েবলটি সংজ্ঞায়িত করুন:

struct a myAValue;

আপনি যদি এটি করতে ভুলে যান বা ঘটনাক্রমে দুটি উত্স ফাইলে এটি সংজ্ঞায়িত করেন তবে লিঙ্কার আপনাকে এই সম্পর্কে জানাতে দেবে।


আপনি একটি লিঙ্কার ত্রুটি পেতে পারেন, বা আপনি নাও পেতে পারেন। সি-তে, লিঙ্কেজ মডেলটি 'সাধারণ' সংজ্ঞাগুলির জন্য মঞ্জুরি দেয়, সুতরাং কোনও প্রারম্ভিক (এবং সম্ভবত একই ইনিশিয়ালাইজার সহ) একাধিক সংজ্ঞা কাজ করতে পারে। এটি একটি 'সাধারণ এক্সটেনশন'। কিছু সংকলক টেন্টিটিভ (নিখোঁজ) সংজ্ঞাগুলিও সমর্থন করে, আমি বিশ্বাস করি।
জোনাথন লেফলার

তারপরে, একটি উত্স ফাইলে, আসল পরিবর্তনশীল সংজ্ঞায়িত করুন:; ... বা ঘটনাক্রমে দুটি উত্স ফাইলে এটি সংজ্ঞায়িত করুন ... :)
জোহানেস স্কাউব - লিটব

এক কৌশল আমি ঘোষণা জন্য ব্যবহার করেছি / সংজ্ঞায়িত ইস্যু শর্তসাপেক্ষে সংজ্ঞায়িত হয় GLOBALযেমন externবা হেডার উপরের কিছুই এবং তারপর হিসাবে ভেরিয়েবল ডিক্লেয়ার GLOBAL struct a myAValue;। বেশিরভাগ উত্স ফাইল থেকে, আপনি #define GLOBAL externসংস্করণটি ব্যবহারের ব্যবস্থা করে ( ভেরিয়েবলগুলি ঘোষণা করে) এবং ঠিক একটি উত্স ফাইল থেকে এটি খালি সংজ্ঞায়িতটি ব্যবহার করে যাতে ভেরিয়েবলগুলি সংজ্ঞায়িত হয়
ট্রিপহাউন্ড

আপনার কাঠামোর নাম টাইপডেফ নামের সি তে থাকতে পারে তবে সি ++ এ নয়।
xuhdev

6

অই:

#ifndef A_H
#define A_H

struct a { 
    int i;
    struct b {
        int j;
    }
};

#endif

আপনি যেখানে যান, এখন আপনাকে কেবল এই ফাইলগুলিতে আহ অন্তর্ভুক্ত করতে হবে যেখানে আপনি এই কাঠামোটি ব্যবহার করতে চান।

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