سؤال

لنفترض أن لدي مجموعة كبيرة وأنا حساب مؤشر إلى تمريرها إلى وظيفة ثانية.كمثال بسيط, شيء من هذا القبيل:

void foo(float* array, float c, unsigned int n)
{
    for (unsigned int i = 0; i < n; ++i)
        array[i] *= c;
}

void bar(float* restrict array, float* restrict array2, unsigned int m, unsigned int n)
{
    for (unsigned int i = 0; i < m; ++i)
        foo(&array[i * n], array2[i], n);
}

هذا كسر قواعد تقيد في شريط() حيث يمكنك تمرير عنوان جزء من مجموعة فو () ، حتى إذا كان لا يمكنك استخدام اسم مستعار جزء من مجموعة ضمن شريط()?

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

المحلول

(جميع الاستشهادات الرجوع إلى N1256, الذي هو C99 بالإضافة إلى التقنية والتصويبات (TC3).)

والتعريف الرسمي restrict ويرد في الفقرة 6.7.3.1.أقتبس أهم subclause أدناه. P هو restrict-مؤهل مؤشر إلى نوع T نطاقها هو كتلة B.مؤشر التعبير E هو ان يكون على أساس P إذا كان يعتمد على قيمة P في حد ذاته لا قيمة P من النقاط.

خلال كل إعدام B, اسمحوا L أي lvalue له &L على أساس P.إذا L يستخدم للوصول إلى قيمة الكائن X أن يعين ، X كما تم تعديل (بأي وسيلة) ، ثم تنطبق الشروط التالية:

  • T لا يجوز const-مؤهل.
  • كل lvalue المستخدمة للوصول إلى قيمة X كما يجب أن يكون عنوان القائمة على P.
  • كل ذلك يعدل X يعتبر أيضا إلى تعديل P, لأغراض هذا subclause.
  • إذا P يتم تعيين قيمة المؤشر التعبير E استنادا إلى آخر مقيد مؤشر كائن P2, المرتبطة مع كتلة B2, ثم إما تنفيذ B2 يجب أن تبدأ قبل تنفيذ B, أو تنفيذ B2 يجب أن تنتهي قبل التعيين.

إذا كان يتم استيفاء هذه الشروط ، ثم سلوك غير معرف.


دعونا ننظر إلى ما القواعد يجب أن أقول عن الوصول إلى أجزاء من bar's array في foo.نبدأ مع array, تقييد مؤهل مؤشر أعلن في المعلمة قائمة bar.من أجل الوضوح ، سوف ألفا-تحويل المعلمات foo:

void foo(float* b, float c, unsigned int n) { /*modify b[i]*/ }

التخزين إلى جانب array كما يتم تعديل من خلال b.وهذا موافق مع بالنقطة الثانية كما &array[i*n] ما يعادل array+(i*n) (انظر §6.5.3.2).

إذا b كان تقييد مؤهل, ثم سيكون علينا التحقق الرابع النقطة مع P​←b, B​←foo, P2​←array, B2​←bar.منذ B هو تداخل داخل B2 (وظائف تتصرف كما لو المضمنة هنا نرى §6.7.3.1.11), الشرط الأول.هناك أيضا واحد instanciation من النقطة الثالثة (الوصول إلى b[i] في foo) وهي ليست مشكلة.

ومع ذلك b لا تقييد المؤهلين.وفقا ل §6.3.2.3.2, "أي تصفيات س, مؤشر إلى غيرس-مؤهل نوع يمكن تحويلها إلى مؤشر س-مؤهل نسخة من نوع ؛ القيم المخزنة في الأصلي وتحويلها مؤشرات يقارن متساوية".ولذلك التحويل من array+(i*n) إلى b محددة و واضحة المعنى ، لذلك البرنامج سلوك محدد.وعلاوة على ذلك ، منذ b لا restrict-مؤهل, أنها لا تحتاج إلى طاعة أي الخطي الشرط.على سبيل المثال التالي foo هو قانوني في تركيبة مع bar:

void qux(float *v, float *w) {
    v[0] += w[0];
}
void foo(float* b, float c, unsigned int n)
{
    qux(b,b);
}

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

نصائح أخرى

لا ، فإن تقييد يعني أن الصفيف لا يمكنه التعبير عن أي شيء ، بحيث يمكنك تمرير الأشياء دون كسر القواعد

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