سؤال

أنا مرتبك قليلاً بشأن القواعد المتعلقة بالمؤشرات المقيدة. ربما يمكن لشخص ما مساعدتي.

  1. هل من القانوني تحديد المؤشرات المقيدة المتداخلة على النحو التالي:

    int* restrict a;
    int* restrict b;
    
    
    a = malloc(sizeof(int));
    
    
    // b = a; <-- assignment here is illegal, needs to happen in child block
    // *b = rand();
    
    
    while(1)
    {
        b = a;  // Is this legal?  Assuming 'b' is not modified outside the while() block
        *b = rand();
    }
    
  2. هل من القانوني اشتقاق قيمة المؤشر المقيدة على النحو التالي:

    int* restrict c;
    int* restrict d;
    
    
    c = malloc(sizeof(int*)*101);
    d = c;
    
    
    for(int i = 0; i < 100; i++)
    {
        *d = i;
        d++;
    }
    
    
    c = d; // c is now set to the 101 element, is this legal assuming d isn't accessed?
    *c = rand();
    

شكرًا! أندرو

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

المحلول

للرجوع إليها ، ها هي restrict تعريف التصفيات المعقدة إلى حد ما (من C99 6.7.3.1 "التعريف الرسمي للتقييد"):

دع D يكون إعلانًا عن معرف عادي يوفر وسيلة لتعيين كائن P كمؤشر مؤهل مقيد لتكوين T.

إذا ظهر D داخل كتلة ولم يكن لديه فئة تخزين خارجي ، فدع B تشير إلى الكتلة. إذا ظهر D في قائمة إعلانات المعلمة لتعريف الوظيفة ، فليكن B يشير إلى الكتلة المرتبطة بها. خلاف ذلك ، دع B تشير إلى كتلة Main (أو كتلة أي وظيفة تسمى في بدء التشغيل في بيئة قائمة بذاتها).

في ما يلي ، يقال إن تعبير المؤشر E يعتمد على الكائن P إذا (في بعض نقطة التسلسل في تنفيذ B قبل تقييم E) تعديل P للإشارة إلى نسخة من كائن الصفيف الذي أشار إليه سابقًا من شأنه أن يغير قيمة E. لاحظ أن "القائمة" محددة فقط للتعبيرات مع أنواع المؤشرات.

أثناء كل تنفيذ لـ B ، دعنا يجب أن يكون أي lvalue قد يكون & l استنادًا إلى P. إذا تم استخدام L للوصول إلى قيمة الكائن x الذي يعينه ، ويتم تعديل x أيضًا (بأي وسيلة) ، ثم تنطبق المتطلبات التالية : لا يجب أن تكون مؤهلة. يجب أن يكون لكل lvalue الأخرى المستخدمة للوصول إلى قيمة x عنوانها بناءً على P. يجب اعتبار كل الوصول الذي يعدل x أيضًا لتعديل p ، لأغراض هذا الفقرة الفرعية. إذا تم تعيين P ، فإن قيمة تعبير المؤشر e تعتمد على كائن مؤشر مقيد آخر p2 ، المرتبط بالكتلة B2 ، فإن تنفيذ B2 يجب أن يبدأ قبل تنفيذ B ، أو تنفيذ B2 قبل مهمة. إذا لم يتم تلبية هذه المتطلبات ، فإن السلوك غير محدد.

هنا تنفيذ B يعني أن جزءًا من تنفيذ البرنامج الذي يتوافق مع عمر كائن مع نوع العددية ومدة التخزين التلقائية المرتبطة بـ B.

قراءتي لما سبق تعني أنه في سؤالك الأول ، a لا يمكن تعيينه ل b, ، حتى داخل كتلة "طفل" - والنتيجة غير محددة. يمكن إجراء مثل هذه المهمة إذا b تم إعلانه في تلك "الكتل الفرعية" ، ولكن منذ ذلك الحين b يُعلن في نفس النطاق a, ، لا يمكن إجراء المهمة.

للسؤال 2 ، الواجبات بين c و d يؤدي أيضًا إلى سلوك غير محدد (في كلتا الحالتين).

الشيء ذي الصلة من المعيار (لكلا السؤالين) هو:

إذا تم تعيين P ، فإن قيمة تعبير المؤشر e تعتمد على كائن مؤشر مقيد آخر p2 ، المرتبط بالكتلة B2 ، فإن تنفيذ B2 يجب أن يبدأ قبل تنفيذ B ، أو تنفيذ B2 قبل مهمة.

نظرًا لأن المؤشرات المقيدة مرتبطة بنفس الكتلة ، فليس من الممكن أن تبدأ الكتلة B2 قبل تنفيذ B ، أو لـ B2 لتنتهي قبل المهمة (نظرًا لأن B و B2 هما نفس الكتلة).

يعطي المعيار مثالًا يوضح هذا الأمر (أعتقد - وضوح restrict الفقرات القصيرة 4 من التعريف على قدم المساواة مع قواعد دقة اسم C ++):

مثال 4:

لا تميز القواعد التي تحد من المهام بين المؤشرات المقيدة بين مكالمة الوظيفة وكتلة متداخلة مكافئة. باستثناء واحد ، فقط المهام "الخارجية إلى الداخل" بين المؤشرات المقيدة المعلنة في الكتل المتداخلة قد حددت السلوك.

{
    int * restrict p1;
    int * restrict q1;

    p1 = q1; //  undefined behavior

    {
        int * restrict p2 = p1; //  valid
        int * restrict q2 = q1; //  valid
        p1 = q2; //  undefined behavior
        p2 = q2; //  undefined behavior
    }
}

نصائح أخرى

ال restrict نوع التصفيات هو دلالة إلى المترجم ، إذا تناولت الذاكرة من قبل restrict-يتم تعديل المؤشر المؤهل ، ولن يصل أي مؤشر آخر إلى نفس الذاكرة. قد يختار المترجم لتحسين الرمز الذي يتضمن restrict-مؤشرات مؤهلة بطريقة قد تؤدي إلى سلوك غير صحيح. تقع على عاتق المبرمج مسؤولية التأكد من استخدام المؤشرات المؤهلة للتقييم حيث كانت مخصصة لاستخدامها. خلاف ذلك ، قد ينتج عن السلوك غير المحدد. (حلقة الوصل)

كما ترون من الوصف أعلاه ، فإن كلتا مهماتك غير قانونية ، والتي قد تعمل في الموظفين التنفيذيين التي ينتجها بعض المترجمين ولكنها تنكسر في الآخرين. لا تتوقع أن ينبع المترجم نفسه من الأخطاء أو التحذيرات restrict مجرد إعطاء فرصة لإجراء بعض التحسين ، والتي يمكن أن تختار عدم القيام بها ، كما في حالة volatile.

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