C البنية التهيئة باستخدام تسميات. كان يعمل، ولكن كيف؟

StackOverflow https://stackoverflow.com/questions/1601201

سؤال

ولقد وجدت بعض البنية رمز التهيئة أمس أن ألقى لي لحلقة. وإليك مثال:

typedef struct { int first; int second; } TEST_STRUCT;
void testFunc() {
    TEST_STRUCT test = {
        second: 2,
        first:  1
    };
    printf("test.first=%d test.second=%d\n", test.first, test.second);
}

والمثير للدهشة (بالنسبة لي)، وهنا إخراج:

-> testFunc
test.first=1 test.second=2

وكما ترون، ويحصل على تهيئة البنية بشكل صحيح. لم أكن البيانات المسمى تدرك يمكن استخدامها من هذا القبيل. رأيت عدة طرق أخرى للقيام البنية التهيئة، ولكن لم أجد أي أمثلة على هذا النوع من التهيئة لبنية على أي من الأسئلة الشائعة C على الانترنت. هو أي شخص على علم كيف / لماذا يعمل هذا؟

هل كانت مفيدة؟

المحلول

وهنا هو الجزء من الدليل دول مجلس التعاون الخليجي وهو ما يفسر بناء الجملة من المهيآت المعينة لكلا البنيات والمصفوفات:

<اقتباس فقرة>   

في مهيئ هيكل، تحديد اسم حقل إلى تهيئة   مع '<م> .fieldname = ' قبل قيمة العنصر. على سبيل المثال، نظرا ل   البنية التالية،

 struct point { int x, y; };
     

والتهيئة التالي

 struct point p = { .y = yvalue, .x = xvalue }; 
     

وما يعادل

 struct point p = { xvalue, yvalue }; 
     

وجملة أخرى التي لها نفس المعنى، عفا عليها الزمن منذ GCC 2.5، هو '<م> FIELDNAME: '، كما هو موضح هنا:

 struct point p = { y: yvalue, x: xvalue };

وصفحة ذات الصلة يمكن العثور هنا .

ويجب أن يكون مترجم لديك وثائق مماثلة.

نصائح أخرى

وهذه ليست تسميات ولا bitfields.

وهذا هو بناء جملة لتهيئة أعضاء البنية التي يعود تاريخها إلى أيام قبل C99. ليست موحدة ولكن تتوفر في مثل دول مجلس التعاون الخليجي.

typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };

في C99، تم إدخال بناء الجملة من أجل تهيئة أعضاء بنية محددة للمرة الأولى في معيار، ولكن يبدو بشكل مختلف قليلا:

typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };

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

- عند استخدام المهيآت المعينة، يتم تهيئة كل شيء لم يحدد عند مستوى الصفر. هذا يساعد على البنيات كبيرة بشكل استثنائي، ومنها مثلا:

typedef struct {
   double a, b, c, d, e;
   char label[100];
} too_many_type;

too_many_type tm = {.a = 1, .e = 2, .b=1.5};
assert(tm.a + tm.b + tm.c + tm.d + tm.e == 4.5);
assert(!strlen(label));

و- كما يمكنك استخدام النموذج الحرفي المجمع لاستخدام هذا النموذج على خط غير التهيئة، منها مثلا:

.
too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};

وهذه هي الميزات الرائعة حقا، ومعتمدة من قبل كل مترجم C التي أستطيع أن أفكر في، ويجري ذلك انها المعيار. إنه لأمر مخز انهم لا يعرف ذلك جيدا.

وانها ليست حقا "وصفت التصريحات"، ولكن وسيلة لإعطاء القيم الأولية إلى الحقول وردت أسماؤهم في البنية.

ودول مجلس التعاون الخليجي يعطي تحذيرا حول "استخدام عفا عليها الزمن من مهيئ المعينة مع ':'"، وفي C99 يجب بدلا من ذلك كتابة:

    TEST_STRUCT test = {
        .second = 2,
        .first =  1
    };

لا يعرف هذا النحو من قبل C قياسي. يقول القسم 6.7.8 Initialization

         designation:
                designator-list =
         designator-list:
                designator
                designator-list designator
         designator:
                [ constant-expression ]
                . identifier

إذا المترجم الخاص بك يقبل التعيين بنقطتين دون رسالة التشخيص فهذا يعني مترجم ليست (أو يتم تكوين لا يكون) المعايير المتوافقة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top