سؤال

يقول المعيار أن إزالة المؤشر الفارغ يؤدي إلى سلوك غير محدد. ولكن ما هو "المؤشر الفارغ"؟ في الكود التالي ، ما نسميه "المؤشر الفارغ":

struct X
{
  static X* get() { return reinterpret_cast<X*>(1); }
  void f() { }
};

int main()
{
  X* x = 0;
  (*x).f(); // the null pointer?  (1)

  x = X::get();
  (*x).f(); // the null pointer?  (2)

  x = reinterpret_cast<X*>( X::get() - X::get() );
  (*x).f(); // the null pointer?  (3)

  (*(X*)0).f(); // I think that this the only null pointer here (4)
}

أفكر هو أن إزالة المؤشر الفارغ يحدث فقط في الحالة الأخيرة. هل انا على حق؟ هل هناك اختلاف بين مؤشرات وقت التجميع الفارغة ووقت التشغيل وفقًا لمعيار C ++؟

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

المحلول

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

نصائح أخرى

يعد التعبير الثابت الصحيح الذي يقييم إلى 0 صالحًا كمؤشر فارغ ، وبالتالي فإن الحالة الأولى هي أيضًا إزالة مؤشر فارغ.

المؤشر الذي يتم تعيينه على 0 عبر بعض الحساب ليس بالضرورة مؤشر فارغ. في معظم التطبيقات ، سوف يتصرف بنفس طريقة مؤشر فارغ ، ولكن هذا غير مضمون وفقًا للمعيار.

C ++ Standard (2003) 4.10

4.10 تحويلات المؤشر

1 ثابت مؤشر فارغ هو تعبير ثابت متكامل (5.19) rvalue من نوع عدد صحيح الذي يقيم إلى الصفر. يمكن تحويل ثابت مؤشر فارغ إلى نوع مؤشر ؛ والنتيجة هي قيمة المؤشر الفارغ لهذا النوع ويمكن تمييزها عن كل قيمة أخرى للمؤشر إلى كائن أو مؤشر إلى نوع الوظيفة. يجب أن تقارن قيمتان مؤشرتان فارغتان من نفس النوع. إن تحويل مؤشر فارغ ثابت إلى مؤشر إلى النوع المؤهل للسيرة CV هو تحويل واحد ، وليس تسلسل تحويل المؤشر متبوعًا بتحويل مؤهل (4.4).

5.2.10 إعادة تفسير

ملاحظة 64) تحويل تعبير ثابت متكامل (5.19) مع القيمة صفر يؤدي دائمًا إلى مؤشر فارغ (4.10) ، ولكن تحويل التعبيرات الأخرى التي تحدث صفرًا لا تحتاج إلى مؤشر فارغ.

1) X* x = 0; (*x).f(); نعم. 0 هو تعبير ثابت متكامل ويتم تحويله إلى ثابت مؤشر فارغ. ثم يمكن تحويل ثابت المؤشر الفارغ إلى قيمة المؤشر الفارغ.

2) x = X::get(); لا ، انظر الملاحظة 64 في 5.2.10

3) x = reinterpret_cast<X*>( X::get() - X::get() ); لا ، انظر الملاحظة 64 في 5.2.10

4) ((x) 0) .f () ؛ نعم. 0 (تعبير ثابت متكامل) -> ثابت المؤشر الفارغ -> قيمة المؤشر الفارغ.

X* x = 0;
(*x).f(); // the null pointer?  (1)

أعتقد أن هذا مؤهل كإطفاء ، على الرغم من ذلك f() لا تستخدم في الواقع this مؤشر ، وليس هناك طرق افتراضية في X. كان رد الفعل الخاص بي هو القول إن هذا حادث ، لكن الآن بعد أن أفكر في الأمر ، لست متأكدًا.

x = X::get();
(*x).f(); // the null pointer?  (2)

ربما مؤشر غير صالح. لست متأكدًا مما إذا كان سيتعطل (انظر أعلاه للتفكير).

x = reinterpret_cast<X*>( X::get() - X::get() );
(*x).f(); // the null pointer?  (3)

هل التعبير X::get() - X::get() تجميع؟ لم أكن أعتقد أنه كان من القانوني طرح مؤشر من مؤشر آخر من هذا القبيل.

تحرير: d'oh! بالطبع إنه قانوني. ماذا كنت أفكر؟ بوضوح ، أنا مارون.

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