عند استخدام مؤشر تقييد في C ، هل من المقبول تغيير متغير باستخدام معرفه الأولي؟

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

  •  30-09-2019
  •  | 
  •  

سؤال

عند استخدام restrict المؤشر في C ، هل من المقبول تغيير المتغير باستخدامه الأولي المعرف؟ فمثلا:

int foo = 0;

int * restrict fooPtr = &foo;
++(*fooPtr);                   // Part 1: foo is 1 (OK)

++foo;                         // Part 2: foo is 2 (Is this OK?)

int * fooPtr2 = &foo;
++(*fooPtr2);                  // Part 3: foo is 3 (BAD: You shouldn't access via a second pointer)

... لقد غيرت قيمة فو عبر فو بعد restrict fooptr تم انشائه.

الجزء 1 تبدو جيدة بالنسبة لي. أنا مرتبك الجزء 2. ومن ما أفهمه restrict, الجزء 3 سيء (يسمح برنامج التحويل البرمجي ، لكن سلوكه غير محدد ، ويعود الأمر إلى المبرمج حتى لا يفعل ذلك).

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

المحلول

لا ، الجزء 2 ليس على ما يرام.

الجزء المحدد من المعيار هو 6.7.3.1/4. هذا القسم كثيف إلى حد ما ، ويأخذ بعض عمليات إعادة القراءة ، ولكن P هو مؤشر مقيد ، و X هو بعض الكائنات التي يتم استخدامها للوصول إليها ، والتي يتم تعديلها. لذلك في مثالك P هو fooPtr و x هو foo. ثم:

يجب على كل lvalue الأخرى المستخدمة للوصول إلى قيمة x أيضًا عنوانها على أساس P.

يتم تعريف "استنادًا إلى" في الفقرة السابقة ، ولتلخيص ، Lvalue foo يفعل ليس احصل على عنوانه بناءً على مؤشر تقييد P. بحيث يتم كسر القاعدة عند الوصول إلى الكائن foo من خلال اسمها الخاص.

الجزء 3 ليس على ما يرام لنفس السبب بالضبط ، lvalue *fooPtr2 لا يعتمد على p أيضًا ، ولكنه يستخدم أيضًا للوصول إلى X.

أقول "ليس موافق" - أن تكون دقيقًا ، يثير مزيج 1+2 سلوكًا غير محدد ، وكذلك مزيج 1+3. طالما أنك لا تصل فعليًا إلى الكائن من خلال مؤشر تقييد ، فإن أيًا من تعريف تقييد "الركلات". إذا أردت أن تتمكن من إزالة الجزء 1 ، والاحتفاظ بمؤشر تقييد غير المستخدم ، ثم 2 و 3 سيكونان على ما يرام.

نصائح أخرى

نعم ، "الجزء 3" هو سلوك غير محدد. من المواصفات C99 (6.7.3 ، الفقرة 7):

إن الكائن الذي يتم الوصول إليه من خلال مؤشر مقيد في Quali له علاقة خاصة مع هذا المؤشر. يتطلب هذا الارتباط ، الذي تم تحديده في 6.7.3.1 أدناه ، أن يستخدم كل ما يصل إلى هذا الكائن ، بشكل مباشر أو غير مباشر ، قيمة هذا المؤشر المحدد.

أود أن أقول #2 سيئة. على سبيل المثال ، قد يتحسن برنامج التحويل البرمجي عن طريق تحميل القيمة في *fooptr في سجل ، ثم اكتب قيمة التسجيل مرة أخرى إلى Foo مرة أخرى لاحقًا - بعد أن يتم فقد ++ foo.

على افتراض أن جميع الأجزاء من سؤالك تحدث في نفس الكتلة ، ليس من المقبول الوصول إلى قيمة foo مباشرة (الجزء 2) ولا للوصول إليه عبر مؤشر آخر (الجزء 3):

  • 6.7.3.1 التعريف الرسمي للتقييد

يجب على كل lvalue الأخرى المستخدمة للوصول إلى قيمة x أيضًا عنوانها على أساس P.

التعريف الرسمي ل restrict من الصعب للغاية المتابعة (على الأقل بالنسبة لي) ، ولكن الوصف الأقل الرسمي التالي أيضًا من المبالغ القياسية بشكل جيد (على الأقل لهذه الحالة):

إن الكائن الذي يتم الوصول إليه من خلال مؤشر مؤهل للتأهل له ارتباط خاص مع هذا المؤشر. يتطلب هذا الارتباط ، المحدد في 6.7.3.1 أدناه ، أن يستخدم جميع الوصول إلى هذا الكائن ، بشكل مباشر أو غير مباشر ، قيمة هذا المؤشر بالذات.

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