আমাদের সি ইউনিয়ন কেন দরকার?


236

ইউনিয়নগুলি কখন ব্যবহার করা উচিত? আমাদের কেন তাদের দরকার?

উত্তর:


252

ইউনিয়নগুলি প্রায়শই পূর্ণসংখ্যা এবং ভাসমানগুলির বাইনারি উপস্থাপনার মধ্যে রূপান্তর করতে ব্যবহৃত হয়:

union
{
  int i;
  float f;
} u;

// Convert floating-point bits to integer:
u.f = 3.14159f;
printf("As integer: %08x\n", u.i);

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

ইউনিয়নগুলি মাঝে মাঝে সি-তে সিউডো-পলিমারফিজম প্রয়োগ করতেও ব্যবহৃত হয়, কোনও কাঠামোর মধ্যে কিছু ট্যাগ দিয়ে বোঝায় যে এটিতে কী ধরণের অবজেক্ট রয়েছে এবং তারপরে সম্ভাব্য প্রকারগুলি একত্রিত করে:

enum Type { INTS, FLOATS, DOUBLE };
struct S
{
  Type s_type;
  union
  {
    int s_ints[2];
    float s_floats[2];
    double s_double;
  };
};

void do_something(struct S *s)
{
  switch(s->s_type)
  {
    case INTS:  // do something with s->s_ints
      break;

    case FLOATS:  // do something with s->s_floats
      break;

    case DOUBLE:  // do something with s->s_double
      break;
  }
}

এটি struct S28 এর পরিবর্তে আকারটি 12 বাইট হতে দেয় ।


uf এর পরিবর্তে uy হওয়া উচিত
অমিত সিং তোমার

1
উদাহরণস্বরূপ, যা উদাহরণস্বরূপ ফ্লোটকে পূর্ণসংখ্যার কাজগুলিতে রূপান্তরিত করে? আমি মনে করি না, যেমন মেমরিতে বিভিন্ন ফরম্যাটে ইনট এবং ফ্লোট সংরক্ষণ করা হয়। আপনি আপনার উদাহরণ ব্যাখ্যা করতে পারেন?
স্পিন_এইট

3
@ স্পিন_এইট: এটি ভাসা থেকে ইনটকে "রূপান্তর" নয়। "ফ্লোটের বাইনারি প্রতিনিধিত্বকে পুনরায় ব্যাখ্যা করার মতো এটি যেন কোনও ইন্টার were" আউটপুটটি 3 নয়: আদর্শআন.এম.কেজওয়ান আমি নিশ্চিত নই যে অ্যাডাম কেন হেক্স হিসাবে মুদ্রণ করছে।
এন্ডোলিথ

@ অ্যাডাম রোজেনফিল্ড আমি আউটপুটে কোনও পূর্ণসংখ্যার রূপান্তরটি সত্যই রূপান্তর করতে পারি নি: পি
দ্য বিস্ট

2
আমি অনুভব করি যে অপরিবর্তিত আচরণের বিষয়ে অস্বীকৃতি অপসারণ করা উচিত। এটি আসলে সংজ্ঞায়িত আচরণ। C99 স্ট্যান্ডার্ডের পাদটীকা union২ দেখুন: ইউনিয়ন অবজেক্টের বিষয়বস্তুগুলি অ্যাক্সেস করতে ব্যবহৃত সদস্য যদি সর্বশেষে কোনও বস্তুতে কোনও মূল্য সঞ্চয় করতে ব্যবহৃত সদস্য হিসাবে একই না হয় তবে মানটির অবজেক্টের উপস্থাপনের উপযুক্ত অংশটি পুনরায় ব্যাখ্যা করা হয় type.২.। বর্ণিত নতুন ধরণের একটি অবজেক্টের উপস্থাপনা (এমন একটি প্রক্রিয়া যা কখনও কখনও "টাইপ পেনিং" নামে পরিচিত)। এটি একটি ফাঁদ উপস্থাপনা হতে পারে।
খ্রিস্টান গিবনস

136

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

typedef union
{
    struct {
        unsigned char byte1;
        unsigned char byte2;
        unsigned char byte3;
        unsigned char byte4;
    } bytes;
    unsigned int dword;
} HW_Register;
HW_Register reg;

তারপরে আপনি নীচে নিবন্ধটি অ্যাক্সেস করতে পারেন:

reg.dword = 0x12345678;
reg.bytes.byte3 = 4;

এন্ডিয়ানাનેસ (বাইট অর্ডার) এবং প্রসেসরের আর্কিটেকচার অবশ্যই গুরুত্বপূর্ণ।

আর একটি দরকারী বৈশিষ্ট্য হ'ল বিট সংশোধক:

typedef union
{
    struct {
        unsigned char b1:1;
        unsigned char b2:1;
        unsigned char b3:1;
        unsigned char b4:1;
        unsigned char reserved:4;
    } bits;
    unsigned char byte;
} HW_RegisterB;
HW_RegisterB reg;

এই কোডের সাহায্যে আপনি রেজিস্টার / মেমরি ঠিকানায় সরাসরি একক বিট অ্যাক্সেস করতে পারেন:

x = reg.bits.b2;

3
@ অ্যাডাম রোজেনফিল্ডের উপরের উত্তরটির সাথে একত্রে আপনার উত্তরটি নিখুঁত পরিপূরক জুটি তৈরি করে: আপনি ইউনিয়নের মধ্যে একটি কাঠামো ব্যবহার করে প্রদর্শিত হন এবং তিনি স্ট্রাক্টের মধ্যে ইউনিয়ন ব্যবহার করে প্রদর্শন করেন । এটি একবারে আমার উভয়ের দরকার আছে: একটি এম্বেড থাকা সিস্টেমে থ্রেডের মধ্যে সি-তে কিছু অভিনব বার্তা-উত্তীর্ণ বহুবর্ষ বাস্তবায়নের জন্য কাঠামোর মধ্যে ইউনিয়নের মধ্যে একটি কাঠামো, এবং আমি বুঝতে পারি না যে যদি আমি আপনার উত্তর দুটি একসাথে না দেখি তবে ।
গ্যাব্রিয়েল স্টেপলস

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

64

নিম্ন স্তরের সিস্টেম প্রোগ্রামিং একটি যুক্তিসঙ্গত উদাহরণ।

আইআইআরসি, আমি উপাদানগুলি বিটগুলিতে ব্রেকডাউন হার্ডওয়্যার রেজিস্টার করতে ইউনিয়নগুলি ব্যবহার করেছি। সুতরাং, আপনি একটি 8-বিট রেজিস্টার অ্যাক্সেস করতে পারেন (যেমনটি ছিল, সেদিন আমি উপাদানটি বিটগুলিতে করেছি ;-)

(আমি সঠিক বাক্য গঠনটি ভুলেছি তবে ...) এই কাঠামোটি একটি নিয়ন্ত্রণ রেজিস্টারকে নিয়ন্ত্রণ_বাইট হিসাবে বা পৃথক বিটের মাধ্যমে অ্যাক্সেস করার অনুমতি দেয়। প্রদত্ত অন্তর্নিহিততার জন্য সঠিক রেজিস্টার বিটগুলিতে বিটস মানচিত্রটি নিশ্চিত করা গুরুত্বপূর্ণ হবে।

typedef union {
    unsigned char control_byte;
    struct {
        unsigned int nibble  : 4;
        unsigned int nmi     : 1;
        unsigned int enabled : 1;
        unsigned int fired   : 1;
        unsigned int control : 1;
    };
} ControlRegister;

3
এটি একটি দুর্দান্ত উদাহরণ! এম্বেড থাকা সফ্টওয়্যারগুলিতে আপনি কীভাবে এই কৌশলটি ব্যবহার করতে পারেন তার একটি উদাহরণ এখানে দেওয়া হয়েছে: edn.com/design/integrated-circuit-design/4394915/…
rzetterberg

34

বস্তুমুখী উত্তরাধিকারের প্রতিস্থাপন হিসাবে আমি এটি বেশ কয়েকটি গ্রন্থাগারে দেখেছি।

যেমন

        Connection
     /       |       \
  Network   USB     VirtualConnection

আপনি যদি সংযোগ "শ্রেণি" উপরের যেকোন একটি হতে চান তবে আপনি এমন কিছু লিখতে পারেন:

struct Connection
{
    int type;
    union
    {
        struct Network network;
        struct USB usb;
        struct Virtual virtual;
    }
};

লাইবিনফিনিটিতে ব্যবহারের উদাহরণ: http://git.0x539.de/?p=infinote.git ;a=blob ;f=libinfinity/common/inf-session.c ;h=3e887f0d63bd754c6b5ec232948027cbbf4d61fc ;hb=HEAD#l74


33

ইউনিয়নগুলি ডেটা সদস্যদের যা পারস্পরিক একচেটিয়া একই মেমরিটি ভাগ করে নেওয়ার অনুমতি দেয়। এম্বেড থাকা সিস্টেমে যেমন মেমরির ঘাটতি হয় তখন এটি বেশ গুরুত্বপূর্ণ।

নিম্নলিখিত উদাহরণে:

union {
   int a;
   int b;
   int c;
} myUnion;

এই ইউনিয়নটি 3 পৃথক int মানগুলির পরিবর্তে একক int এর স্থান গ্রহণ করবে। ব্যবহারকারী মান সেট করেন তাহলে একটি , এবং তারপর মান সেট , এটা মান ওভাররাইট করবে একটি যেহেতু তারা উভয় একই মেমরির অবস্থান ভাগ করছেন।


29

প্রচুর ব্যবহার শুধু grep union /usr/include/*বা অনুরূপ ডিরেক্টরিতে। বেশিরভাগ unionকেসটি ক structএবং একটি সদস্যের মধ্যে আবৃত থাকে যাতে ইউনিয়নে কোন উপাদানটি অ্যাক্সেস করতে হয় তা জানায়। উদাহরণস্বরূপ man elfবাস্তব জীবনের বাস্তবায়নের জন্য চেকআউট ।

এটিই মূল নীতি:

struct _mydata {
    int which_one;
    union _data {
            int a;
            float b;
            char c;
    } foo;
} bar;

switch (bar.which_one)
{
   case INTEGER  :  /* access bar.foo.a;*/ break;
   case FLOATING :  /* access bar.foo.b;*/ break;
   case CHARACTER:  /* access bar.foo.c;*/ break;
}

ঠিক আমি খুঁজছেন ছিল কি ! কিছু উপবৃত্তাকার প্যারামিটারটি প্রতিস্থাপনের জন্য খুব দরকারী :)
নিকোলাস ভোরন

17

এখানে আমার নিজস্ব কোডবেস থেকে একটি ইউনিয়নের উদাহরণ রয়েছে (মেমরি থেকে এবং প্যারাফ্রেস করা তাই এটি সঠিক নাও হতে পারে)। এটি আমি তৈরি করা দোভাষীগুলিতে ভাষার উপাদানগুলি সঞ্চয় করতে ব্যবহৃত হয়েছিল। উদাহরণস্বরূপ, নিম্নলিখিত কোড:

set a to b times 7.

নিম্নলিখিত ভাষার উপাদানগুলি নিয়ে গঠিত:

  • প্রতীক [সেট]
  • পরিবর্তনশীল [এক]
  • প্রতীক [আপনি]
  • পরিবর্তনশীল [B]
  • প্রতীক [বার]
  • ধ্রুব [7]
  • প্রতীক [।]

ভাষার উপাদানগুলি ' #define' এর মান হিসাবে এইভাবে সংজ্ঞায়িত হয়েছিল :

#define ELEM_SYM_SET        0
#define ELEM_SYM_TO         1
#define ELEM_SYM_TIMES      2
#define ELEM_SYM_FULLSTOP   3
#define ELEM_VARIABLE     100
#define ELEM_CONSTANT     101

এবং প্রতিটি উপাদান সংরক্ষণের জন্য নিম্নলিখিত কাঠামোটি ব্যবহার করা হয়েছিল:

typedef struct {
    int typ;
    union {
        char *str;
        int   val;
    }
} tElem;

তারপরে প্রতিটি উপাদানের আকার ছিল সর্বোচ্চ ইউনিয়নের আকার (প্রকারের জন্য 4 বাইট এবং ইউনিয়নের জন্য 4 বাইট, যদিও সেগুলি আদর্শ মানের, প্রকৃত বাস্তবায়নের উপর নির্ভর করে আকার)।

একটি "সেট" উপাদান তৈরি করতে, আপনি ব্যবহার করবেন:

tElem e;
e.typ = ELEM_SYM_SET;

একটি "ভেরিয়েবল [বি]" উপাদান তৈরি করতে, আপনি এই ব্যবহার করবেন:

tElem e;
e.typ = ELEM_VARIABLE;
e.str = strdup ("b");   // make sure you free this later

একটি "ধ্রুবক [7]" উপাদান তৈরি করতে, আপনি এটি ব্যবহার করবেন:

tElem e;
e.typ = ELEM_CONSTANT;
e.val = 7;

এবং আপনি সহজেই এটি প্রসারিত করতে পারেন ( float flt) বা যুক্তি ( struct ratnl {int num; int denom;}) এবং অন্যান্য ধরণের অন্তর্ভুক্ত করতে।

মৌলিক প্রতিজ্ঞা যে strএবং valনা মেমরি সংলগ্ন, তারা আসলে ওভারল্যাপ, তাই এটি যেখানে গঠন মেমরির অবস্থানে ভিত্তি করে মেমরি একই ব্লকে একটি ভিন্ন দৃশ্য পেয়ে, এখানে দেখানো হয়েছে, একটি উপায় আছে 0x1010এবং পূর্ণসংখ্যার এবং পয়েন্টার উভয় 4 বাইট:

       +-----------+
0x1010 |           |
0x1011 |    typ    |
0x1012 |           |
0x1013 |           |
       +-----+-----+
0x1014 |     |     |
0x1015 | str | val |
0x1016 |     |     |
0x1017 |     |     |
       +-----+-----+

এটি যদি কেবল কোনও কাঠামোর মধ্যে থাকে তবে এটি দেখতে এটির মতো হবে:

       +-------+
0x1010 |       |
0x1011 |  typ  |
0x1012 |       |
0x1013 |       |
       +-------+
0x1014 |       |
0x1015 |  str  |
0x1016 |       |
0x1017 |       |
       +-------+
0x1018 |       |
0x1019 |  val  |
0x101A |       |
0x101B |       |
       +-------+

করা উচিত make sure you free this laterমন্তব্য ধ্রুবক উপাদান থেকে সরানো হতে?
ট্রেভর

হ্যাঁ, @ ট্রেভর, যদিও আমি বিশ্বাস করতে পারি না যে আপনি প্রথম ব্যক্তি যিনি এটি গত 4+ বছর ধরে দেখেছেন :-) স্থির, এবং তার জন্য ধন্যবাদ।
paxdiablo

7

আমি বলতে চাই মেমরির পুনঃব্যবহার করা আরও সহজ করে তোলে যা বিভিন্ন উপায়ে ব্যবহার করা যেতে পারে, যেমন মেমরি সঞ্চয় করে। যেমন আপনি কিছু "বৈকল্পিক" কাঠামো করতে চান যা একটি সংক্ষিপ্ত স্ট্রিং পাশাপাশি একটি সংখ্যা সংরক্ষণ করতে সক্ষম:

struct variant {
    int type;
    double number;
    char *string;
};

একটি 32 বিট সিস্টেমে এটির প্রতিটি উদাহরণের জন্য কমপক্ষে 96 বিট বা 12 বাইট ব্যবহার করা হবে variant

ইউনিয়ন ব্যবহার করে আপনি আকারটি 64 বিট বা 8 বাইটে হ্রাস করতে পারবেন:

struct variant {
    int type;
    union {
        double number;
        char *string;
    } value;
};

আপনি আরও বিভিন্ন পরিবর্তনশীল প্রকার ইত্যাদি যুক্ত করতে চাইলে আপনি আরও বেশি সঞ্চয় করতে সক্ষম হবেন এটি সত্য হতে পারে, আপনি শূন্য পয়েন্টার castালাইয়ের অনুরূপ জিনিসগুলি করতে পারেন - তবে ইউনিয়ন এটিকে অনেক বেশি অ্যাক্সেসযোগ্য পাশাপাশি টাইপ করার মতো করে তোলে নিরাপদ। এই ধরনের সঞ্চয়গুলি বিশাল শোনাচ্ছে না তবে আপনি এই স্ট্রাক্টের সমস্ত দৃষ্টান্তের জন্য ব্যবহৃত মেমরির এক তৃতীয়াংশ সংরক্ষণ করছেন।


5

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

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

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

typedef union MyUnion MYUNION;
union MyUnion
{
   int MyInt;
   float MyFloat;
};

আপনি সর্বশেষে সেট করেছেন তার উপর নির্ভর করে মাইইউনিয়নে কেবলমাত্র কোনও ইন্ট বা একটি ফ্লোট থাকবে । সুতরাং এটি করছেন:

MYUNION u;
u.MyInt = 10;

আপনার এখন 10 এর সমান ইন্টি;

u.MyFloat = 1.0;

আপনি এখন 1.0 এর সমান ফ্লোট ধারণ করে holds এটি আর কোন int রাখে না। স্পষ্টত এখন আপনি যদি প্রিন্টফ চেষ্টা করেন এবং করেন ("MyInt =% d", u.MyInt); তবে আপনি সম্ভবত একটি ত্রুটি পেতে চলেছেন, যদিও আমি নির্দিষ্ট আচরণ সম্পর্কে নিশ্চিত নই of

ইউনিয়নের আকার তার বৃহত্তম ক্ষেত্রের আকার দ্বারা নির্ধারিত হয়, এক্ষেত্রে ভাসা।


1
sizeof(int) == sizeof(float)( == 32) সাধারণত
নিক টি

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

4

ইউনিয়নগুলি যখন আপনি হার্ডওয়্যার, ডিভাইস বা নেটওয়ার্ক প্রোটোকল দ্বারা সংজ্ঞায়িত স্ট্রাক্টগুলি মডেল করতে চান বা যখন আপনি প্রচুর পরিমাণে অবজেক্ট তৈরি করেন এবং স্থান সংরক্ষণ করতে চান তখন ব্যবহৃত হয়। আপনার সত্যিকারের 95% সময় প্রয়োজন নেই যদিও, সহজে-ডিবাগ কোড সহ আটকে দিন।


4

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

typedef union
{
    UINT8 buffer[PACKET_SIZE]; // Where the packet size is large enough for
                               // the entire set of fields (including the payload)

    struct
    {
        UINT8 size;
        UINT8 cmd;
        UINT8 payload[PAYLOAD_SIZE];
        UINT8 crc;
    } fields;

}PACKET_T;

// This should be called every time a new byte of data is ready 
// and point to the packet's buffer:
// packet_builder(packet.buffer, new_data);

void packet_builder(UINT8* buffer, UINT8 data)
{
    static UINT8 received_bytes = 0;

    // All range checking etc removed for brevity

    buffer[received_bytes] = data;
    received_bytes++;

    // Using the struc only way adds lots of logic that relates "byte 0" to size
    // "byte 1" to cmd, etc...
}

void packet_handler(PACKET_T* packet)
{
    // Process the fields in a readable manner
    if(packet->fields.size > TOO_BIG)
    {
        // handle error...
    }

    if(packet->fields.cmd == CMD_X)
    {
        // do stuff..
    }
}

সম্পাদনা করুন endianness এবং struct প্যাডিং সম্পর্কে মন্তব্য, বৈধ, এবং মহান উদ্বেগ। আমি এম্বেডড সফ্টওয়্যারগুলিতে কোডের এই বডিটি প্রায় সম্পূর্ণ ব্যবহার করেছি, যার বেশিরভাগ অংশে আমার পাইপের উভয় প্রান্তের নিয়ন্ত্রণ ছিল।


1
নিম্নলিখিত কারণগুলির কারণে 2 টি ভিন্ন ভিন্ন প্ল্যাটফর্মের মাধ্যমে ডেটা আদান প্রদান করা হলে এই কোডটি (বেশিরভাগ সময়) কাজ করবে না: 1) এন্ডিয়েনসনেস আলাদা হতে পারে। 2) কাঠামো মধ্যে প্যাডিং।
মাহোরি

@ রাভি আমি অন্তর্নিহিতা এবং প্যাডিং সম্পর্কিত উদ্বেগগুলির সাথে একমত। তবে এটি জানা উচিত যে আমি এম্বেড প্রকল্পগুলিতে এটি একচেটিয়াভাবে ব্যবহার করেছি। যার বেশিরভাগ আমি পাইপের উভয় প্রান্তকেই নিয়ন্ত্রণ করেছিলাম।
অ্যাডাম লুইস

1

ইউনিয়নগুলি দুর্দান্ত। ইউনিয়নগুলির একটি চতুর ব্যবহার আমি দেখেছি কোনও ইভেন্টের সংজ্ঞা দেওয়ার সময় সেগুলি ব্যবহার করা। উদাহরণস্বরূপ, আপনি সিদ্ধান্ত নিতে পারেন যে কোনও ইভেন্ট 32 বিট।

এখন, 32 টি বিটের মধ্যে, আপনি ইভেন্টের প্রেরকের সনাক্তকারী হিসাবে প্রথম 8 টি বিট নির্দিষ্ট করতে পছন্দ করতে পারেন ... কখনও কখনও আপনি ইভেন্টটিকে পুরোপুরি ডিল করেন, কখনও কখনও আপনি এটি বিছিন্ন করেন এবং এর উপাদানগুলি তুলনা করেন। ইউনিয়নগুলি আপনাকে উভয় ক্ষেত্রেই নমনীয়তা দেয়।

ইউনিয়ন ইভেন্ট
{
  স্বাক্ষরবিহীন দীর্ঘ ইভেন্টকোড;
  স্বাক্ষরযুক্ত চর ইভেন্ট ইভেন্টস [4];
};

1

VARIANTসিওএম ইন্টারফেসে এর ব্যবহার কী ? এর দুটি ক্ষেত্র রয়েছে - "টাইপ" এবং একটি ইউনিয়ন একটি আসল মান ধারণ করে যা "টাইপ" ক্ষেত্রের উপর নির্ভর করে চিকিত্সা করা হয়।


1

স্কুলে, আমি এই জাতীয় ইউনিয়নগুলি ব্যবহার করেছি:

typedef union
{
  unsigned char color[4];
  int       new_color;
}       u_color;

আমি এটি আরও সহজে রঙগুলি পরিচালনা করতে ব্যবহার করেছি, >> এবং << অপারেটর ব্যবহারের পরিবর্তে, আমাকে আমার চর অ্যারের বিভিন্ন সূচকটি পেরিয়ে যেতে হয়েছিল।


1

আমি এম্বেড থাকা ডিভাইসগুলির জন্য কোডিং করার সময় ইউনিয়ন ব্যবহার করেছি। আমার সি ইনট রয়েছে যা 16 বিট দীর্ঘ। এবং যখন আমাকে EEPROM থেকে / স্টোর থেকে পড়তে হবে তখন আমাকে উচ্চতর 8 টি বিট এবং নিম্ন 8 বিটগুলি উদ্ধার করতে হবে। সুতরাং আমি এইভাবে ব্যবহার করেছি:

union data {
    int data;
    struct {
        unsigned char higher;
        unsigned char lower;
    } parts;
};

কোডটি পড়া সহজ হয় তাই এটি স্থানান্তরিত হয় না।

অন্যদিকে, আমি কিছু পুরানো সি ++ এসএলএল কোড দেখেছি যা স্টাইল বরাদ্দকারীর জন্য ইউনিয়ন ব্যবহার করে। আপনি যদি আগ্রহী হন তবে স্যাজি স্টাইল উত্স কোডটি পড়তে পারেন । এখানে এটির একটি অংশ:

union _Obj {
    union _Obj* _M_free_list_link;
    char _M_client_data[1];    /* The client sees this.        */
};

1
structআপনার higher/ আপনার চারপাশে একটি গ্রুপিংয়ের প্রয়োজন হবে না lower? এই মুহুর্তে উভয়েরই কেবল প্রথম বাইটের দিকে নির্দেশ করা উচিত।
মারিও

@ মারিও আহ ঠিক আছে, আমি এটি হাতে হাতে লিখেছি এবং এটি সম্পর্কে ভুলে গেছি, ধন্যবাদ
মি কিয়াও

1
  • বিভিন্ন ফাইল রেকর্ড টাইপযুক্ত একটি ফাইল।
  • একটি নেটওয়ার্ক ইন্টারফেসে বিভিন্ন অনুরোধের ধরণ রয়েছে।

এটি একবার দেখুন: X.25 বাফার কমান্ড হ্যান্ডলিং

অনেকগুলি সম্ভাব্য এক্স.25 কমান্ডগুলির মধ্যে একটি একটি বাফারে প্রাপ্ত হয় এবং সমস্ত সম্ভাব্য কাঠামোর একটি ইউনিয়ন ব্যবহার করে স্থানে পরিচালনা করা হয়।


আপনি দয়া করে এই দুটি উদাহরণ ব্যাখ্যা করতে পারেন .আমি এর মানে কীভাবে এটি ইউনিয়নের সাথে সম্পর্কিত
অমিত সিং তোমার

1

সি এর প্রাথমিক সংস্করণগুলিতে, সমস্ত কাঠামো ঘোষণাগুলি ক্ষেত্রগুলির একটি সাধারণ সেট ভাগ করবে। প্রদত্ত:

struct x {int x_mode; int q; float x_f};
struct y {int y_mode; int q; int y_l};
struct z {int z_mode; char name[20];};

একটি সংকলক মূলত কাঠামোর আকারের (এবং সম্ভবত সারিবদ্ধকরণ) একটি টেবিল এবং কাঠামোর সদস্যদের নাম, প্রকার এবং অফসেটের একটি পৃথক টেবিল তৈরি করতে পারে। সংকলকটি কোন কাঠামোর সাথে সম্পর্কিত ছিল তা ট্র্যাক করেনি, এবং টাইপ এবং অফসেটটি মিলে গেলে (সদস্য qহিসাবে struct xএবং এর সাথে struct y) দুটি কাঠামোগত একই নামের সদস্য থাকতে দেয় । P যদি কোনও কাঠামোর ধরণের পয়েন্টার হয়, p-> q পয়েন্টার পিতে "q" এর অফসেট যুক্ত করবে এবং ফলাফলের ঠিকানা থেকে "ইনট" আনবে।

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

ইউনিয়নগুলির এই শূন্যস্থান পূরণের ক্ষমতার একটি অপরিহার্য অংশটি হ'ল ইউনিয়ন সদস্যের পয়েন্টারটিকে সেই সদস্য সমন্বিত যে কোনও ইউনিয়নে পয়েন্টারে রূপান্তর করা যায় এবং যে কোনও ইউনিয়নে একটি পয়েন্টারকে কোনও সদস্যকে পয়েন্টারে রূপান্তর করা যেতে পারে। C89 স্ট্যান্ডার্ড স্পষ্টভাবে বলতে না পারলেও একটি ভোটদান T*একটি সরাসরি U*একটি পয়েন্টার তা কোন ইউনিয়ন টাইপ কাস্ট উভয় ধারণকারী সমতূল্য ছিল Tএবং U, এবং তারপর ভোটদান যে U*, আধুনিক ঢালাই ক্রম কোন সংজ্ঞায়িত আচরণ দ্বারা প্রভাবিত হতে হবে ইউনিয়ন টাইপ ব্যবহৃত, এবং স্ট্যান্ডার্ড থেকে একটি সরাসরি ঢালাই জন্য কোন বিপরীত শব্দার্থবিদ্যা উল্লেখ করা হয়নি Tকরতে U। তদ্ব্যতীত, যেখানে কোনও ফাংশন অজানা উত্সের পয়েন্টার পেয়েছে, কোনও রূপটি T*রূপান্তর করে এর মাধ্যমে কোনও অবজেক্ট লেখার আচরণT*একটি থেকেU*, এবং তারপরে অবজেক্টটি পড়া U*টাইপের সদস্যের মাধ্যমে ইউনিয়ন লেখার Tএবং টাইপ হিসাবে পড়া সমতুল্য U, যা কয়েকটি ক্ষেত্রে স্ট্যান্ডার্ড-সংজ্ঞায়িত হবে (উদাহরণস্বরূপ সাধারণ প্রাথমিক অনুক্রমের সদস্যদের অ্যাক্সেস করার সময়) এবং বাস্তবায়ন-সংজ্ঞায়িত (পরিবর্তে অপরিজ্ঞাত ) বাকি জন্য। প্রোগ্রামগুলির পক্ষে ইউনিয়নের ধরণের প্রকৃত বস্তুগুলির সাথে সিআইএস গ্যারান্টিগুলি অপব্যবহার করা বিরল ছিল, তবে অজানা উত্সের বস্তুগুলিকে পয়েন্টারগুলির মতো ইউনিয়ন সদস্যদের সাথে পয়েন্টারের মতো আচরণ করতে হয়েছিল এবং এর সাথে সম্পর্কিত আচরণগত গ্যারান্টি থাকতে হবে তা কাজে লাগানো আরও সাধারণ বিষয় ছিল।


আপনি কি এর উদাহরণ দিতে পারেন: a এমন একটি ফাংশন লেখা সম্ভব ছিল যা একাধিক ধরণের কাঠামোর বিনিময়ে কিছু কার্যকর ক্রিয়াকলাপ সম্পাদন করতে পারে ` একই নামের একাধিক স্ট্রাকচার সদস্য কীভাবে ব্যবহার করা যেতে পারে? যদি দুটি স্ক্র্যাচারের একই ডেটা প্রান্তিককরণ থাকে এবং এইভাবে একই নামের একই সদস্য এবং আপনার উদাহরণ হিসাবে একই অফসেট থাকে, তবে আমি কোন কাঠামো থেকে প্রকৃত ডেটা উপার্জন করব? (মান)। দুটি কাঠামোর একই প্রান্তিককরণ এবং একই সদস্য রয়েছে তবে তাদের উপর আলাদা মান রয়েছে। আপনি কি দয়া করে এটি বিস্তারিতভাবে বর্ণনা করতে পারেন
হার্ডসম্যান

@ হার্ডসম্যান: সি এর প্রাথমিক সংস্করণগুলিতে, স্ট্রাক্ট সদস্যের নামটি একটি প্রকার এবং একটি অফসেট সংযুক্ত করে। বিভিন্ন স্ট্রাকচারের দুটি সদস্যের নাম একই রকম হতে পারে যদি এবং কেবল তাদের প্রকার এবং অফসেটগুলি মিলে যায়। স্ট্রাক্ট সদস্য fooযদি intঅফসেট 8 সহ একটি হয় তবে anyPointer->foo = 1234;তার অর্থ "কোনও পয়েন্টারে ঠিকানা নিন, এটি 8 বাইট দ্বারা স্থানচ্যুত করুন এবং ফলাফলের ঠিকানায় 1234 মানের একটি পূর্ণসংখ্যা স্টোর সম্পাদন করুন The সংকলকটি anyPointerসনাক্ত বা সনাক্তকরণের প্রয়োজন হবে না যে কোনও কাঠামোর ধরণ যা fooএর সদস্যদের মধ্যে তালিকাভুক্ত করেছিল
ক্যাট

পয়েন্টারের সাহায্যে আপনি পয়েন্টারের 'উত্স' নির্বিশেষে যে কোনও ঠিকানা চিহ্নিত করতে পারেন, এটি সত্য, তবে তবে কাঠামোগত সদস্যদের টেবিল এবং তাদের নামগুলি রাখার জন্য সংকলকটির মূল বক্তব্য কী (আপনি আপনার পোস্টে যেমন বলেছেন) যদি আমি তথ্য আনতে পারি কোনও নির্দিষ্ট বিন্দুতে কোনও সদস্যের ঠিকানা জেনে কোনও পয়েন্টার সহ? এবং যদি সংকলক anyPointerস্ট্রাক্ট সদস্যের সাথে পরিচয় দেয় কিনা তা যদি জানেন না , তবে সংকলক to have a member with the same name only if the type and offset matchedআপনার পোস্টের এই শর্তটি কীভাবে পরীক্ষা করবে ?
হার্ডসম্যান

@ হার্ডসম্যান: সংকলক কাঠামোর সদস্যদের নামের তালিকা রাখবে কারণ এর যথাযথ আচরণ p->fooনির্ভর করে টাইপ এবং অফসেটের উপর foo। মূলত, p->fooছিল সংক্ষিপ্ত *(typeOfFoo*)((unsigned char*)p + offsetOfFoo)। আপনার পরবর্তী প্রশ্ন হিসাবে, যখন কোনও সংকলক স্ট্রাক্ট সদস্য সংজ্ঞাটির মুখোমুখি হয়, তখন প্রয়োজন হয় যে সেই নামটি সহ কোনও সদস্যই উপস্থিত নেই, বা সেই নামের সদস্যটির একই ধরণ এবং অফসেট রয়েছে; আমি অনুমান করব যে কোনও মেলে না এমন স্ট্রাক্ট সদস্য সংজ্ঞা থাকলে অস্তিত্ব নষ্ট হয়ে গেছে, তবে কীভাবে এটি ত্রুটিগুলি পরিচালনা করেছিল তা আমি জানি না।
ক্যাট

0

একটি সহজ এবং খুব দরকারী উদাহরণ, ....

কল্পনা করুন:

আপনার কাছে uint32_t array[2]রয়েছে এবং বাইট চেইনের তৃতীয় এবং চতুর্থ বাইট অ্যাক্সেস করতে চান। আপনি করতে পারে *((uint16_t*) &array[1])। তবে দুঃখের সাথে এই কঠোর এলিয়াসিং বিধি ভঙ্গ করে!

তবে পরিচিত সংকলকগুলি আপনাকে নিম্নলিখিতটি করতে অনুমতি দেয়:

union un
{
    uint16_t array16[4];
    uint32_t array32[2];
}

প্রযুক্তিগতভাবে এটি এখনও নিয়ম লঙ্ঘন। তবে সমস্ত জ্ঞাত মান এই ব্যবহারকে সমর্থন করে।

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