c - questions - typedef شرح




typedef struct مقابل تعريفات البنية (8)

هذا السؤال لديه بالفعل إجابة هنا:

أنا مبتدئ في برمجة C ، ولكن كنت أتساءل ما هو الفرق بين استخدام الرموز المميزة لـ typedef عند تعريف بنية مقابل عدم استخدام الرموز المميزة لـ typedef. يبدو لي أنه لا يوجد فرق حقيقي ، فهم يحققون نفس الشيء.

struct myStruct{
    int one;
    int two;
};

ضد.

typedef struct{
    int one;
    int two;
}myStruct;

أرى بعض التوضيح في هذا الشأن. لا تعرّف C و C ++ الأنواع بشكل مختلف. كان C ++ في الأصل لا شيء أكثر من مجموعة إضافية من الإضافات في أعلى C.

المشكلة أن جميع مطوري C / C ++ لديهم اليوم ، أ) الجامعات لم تعد تدرس الأساسيات ، و (ب) لا يفهم الناس الفرق بين التعريف والإعلان.

السبب الوحيد لوجود مثل هذه التعريفات والتعريفات بحيث يمكن linker حساب تعويضات العناوين إلى الحقول في البنية. هذا هو السبب في أن معظم الناس يفلتون من الكود الذي تمت كتابته بشكل صحيح - لأن المترجم قادر على تحديد العنوان. تبرز المشكلة عندما يحاول شخص ما القيام بشيء ما ، كقائمة الانتظار ، أو قائمة مرتبطة ، أو دعم بنية O-S.

يبدأ الإعلان بـ "struct" ، يبدأ التعريف بـ "typedef".

علاوة على ذلك ، تحتوي البنية على تسمية تعريفية ، وملصق محدد. معظم الناس لا يعرفون هذا ويستخدمون تسمية الإعلان إلى الأمام كتسمية تعريف.

خطأ:

struct myStruct
   {
   int field_1;
   ...
   };

لقد استخدموا للتو الإعلان الأمامي لتسمية البنية - لذا فإن المحول علمًا بذلك - ولكنه ليس نوعًا محددًا فعليًا. يمكن أن يحسب المحول البرمجي العنوان - لكن هذه ليست الطريقة التي كان من المفترض أن يتم استخدامها ، لأسباب سوف أقوم بعرضها للحظات.

يجب على الأشخاص الذين يستخدمون هذا الشكل من الإعلان أن يضعوا "الهيكل" في كل إشارة إليه عمليًا ، لأنه ليس نوعًا جديدًا رسميًا.

وبدلاً من ذلك ، ينبغي الإعلان عن أي بنية لا تشير إلى نفسها ، ويتم تعريفها بهذه الطريقة فقط:

typedef struct
   {
   field_1;
   ...
   }myStruct;

الآن هو نوع حقيقي ، وعند استخدامه يمكنك استخدامه في 'myStruct' دون الحاجة إلى إرفاقه بكلمة 'struct'.

إذا كنت تريد متغير مؤشر إلى تلك البنية ، فعليك تضمين ملصق ثانوي:

typedef struct
   {
   field_1;
   ...
   }myStruct,*myStructP;

الآن لديك متغير مؤشر إلى تلك البنية ، مخصص لها.

الإعلان الأمامي

الآن ، ها هي الأشياء الفاخرة ، كيف يعمل الإعلان الأمامي. إذا كنت تريد إنشاء نوع يشير إلى نفسه ، مثل عنصر قائمة انتظار أو قائمة ارتباط ، يجب عليك استخدام بيان إعادة توجيه. المحول البرمجي لا يعتبر الهيكل محددًا حتى يصل إلى الفاصلة المنقوطة في النهاية ، لذا تم الإعلان عنه قبل هذه النقطة.

typedef struct myStructElement
   {
   myStructElement*  nextSE;
   field_1;
   ...
   }myStruct;

الآن ، يعرف المترجم أنه على الرغم من أنه لا يعرف ما هو النوع بالكامل حتى الآن ، فإنه لا يزال بإمكانه الرجوع إليه باستخدام المرجع الأمامي.

يرجى ذكر و typedef الهياكل الخاصة بك بشكل صحيح. هناك في الواقع سبب.


إذا كنت تستخدم struct بدون typedef ، فستحتاج دائمًا إلى الكتابة

struct mystruct myvar;

من غير القانوني أن يكتب

mystruct myvar;

إذا كنت تستخدم typedef لا تحتاج إلى البادئة struct بعد الآن.


في C (وليس C ++) ، يجب عليك الإعلان عن متغيرات البنية مثل:

struct myStruct myVariable;

لكي تتمكن من استخدام myStruct myVariable; بدلاً من ذلك ، يمكنك كتابة البنية:

typedef struct myStruct someStruct;
someStruct myVariable;

يمكنك دمج تعريف struct و typedef s في عبارة واحدة والتي تعلن struct مجهولة و typedef s.

typedef struct { ... } myStruct;

في C ، تعتبر الكلمات الرئيسية لمعرف النوع الخاصة بالبنيات والنقابات والتعدادات إلزامية ، أي يجب عليك دائمًا إدخال اسم النوع ( علامة ) مع struct أو enum أو enum عند الإشارة إلى النوع.

يمكنك التخلص من الكلمات الرئيسية باستخدام typedef ، وهو شكل من أشكال المعلومات المخفية لأن النوع الفعلي للكائن لن يكون مرئيًا عند التصريح به.

ولذلك يوصى (انظر على سبيل المثال ، دليل نمط ترميز Linux kernel ، الفصل 5) للقيام بذلك فقط عندما تريد بالفعل إخفاء هذه المعلومات وليس فقط لحفظ بضع ضربات المفاتيح.

مثال على متى يجب عليك استخدام typedef سيكون نوع معتم يستخدم فقط مع وظائف / وحدات الماكرو الملحقة.


مع المثال الأخير ، يمكنك حذف الكلمة الأساسية struct عند استخدام البنية. في كل مكان في شفرتك ، يمكنك كتابة:

myStruct a;

بدلا من

struct myStruct a;

هذا حفظ بعض الكتابة ، وربما تكون أكثر قابلية للقراءة ، ولكن هذه مسألة ذوق


هناك اختلاف آخر لم يتم الإشارة إليه هو أن إعطاء البنية اسمًا (أي بنية myStruct) يتيح لك أيضًا تقديم الإعلانات المستقبلية للبنية. في بعض الملفات الأخرى ، يمكنك كتابة:

struct myStruct;
void doit(struct myStruct *ptr);

دون الحاجة إلى الوصول إلى التعريف. ما أوصيك به هو الجمع بين أمرين:

typedef struct myStruct{
    int one;
    int two;
} myStruct;

هذا يمنحك راحة اسم typedef أكثر إيجازاً ولكن لا يزال يسمح لك باستخدام اسم البنية الكاملة إذا كنت في حاجة.


يتم استخدام typedef ، كما هو الحال مع التركيبات الأخرى ، لإعطاء نوع بيانات اسمًا جديدًا. في هذه الحالة ، يتم إجراء ذلك غالبًا لجعل الشفرة أكثر نظافة:

struct myStruct blah;

ضد.

myStruct blah;

ينشئ التعليمة البرمجية التالية بنية مجهولة مع الاسم المستعار myStruct :

typedef struct{
    int one;
    int two;
} myStruct;

لا يمكنك الرجوع إليه بدون الاسم المستعار لأنك لا تحدد معرّفًا للبنية.





typedef