سؤال

هل التحويل التالي آمن؟

int b[10][10];
char *x;
int a[]={0,1,2,3,4,5,6,7,8,9};

for(int i=0;i<10;i++)
  for(int j=0;j<10;j++)
    b[i][j]=a[i];

for(x=(char *)&b[0];x<=(char *)&b[9][9];x+=sizeof(a+1)) // Problem lies here!
    printf("%d\n",*x);

لا أعتقد أن التحويل أعلاه في for حلقة آمنة (أعتقد أنه من النظام الأساسي تعتمد). يرجى تصحيح لي إذا كنت مخطئا. أنا مندهش لأن الكود يجمع دون إعطاء أي تحذيرات حتى عند ترجمة باستخدام -Wall -pedantic خيارات في دول مجلس التعاون الخليجي.

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

المحلول

هذا كل شيء لديه فرصة لأن تكون قانوني لسبب واحد وسبب واحد فقط: 2D int يتم إعادة تفسير كائن الصفيف كصفيف char أشياء. في حين أن إعادة تفسير الذاكرة في الحالة العامة يؤدي إلى سلوك غير محدد، فإن مواصفات اللغة تسمح صراحة "مجموعة من [سحر [موقعة / غير موقعة] إعادة تفسير الكائنات من أي نوع.

ومع ذلك، فإن مشكلة السلامة الرسمية واحدة لا تزال هناك. اللغة لا تضمن أن أي نمط بت هو قيمة صالحة لل char اكتب. محاولتك لقراءة ذاكرة إعادة تفسير من خلال char اكتب يمكن أن يسبب نظريا سلوك غير محدد إذا كان يواجه تمثيل الفخ char. وبعد من أجل أن تكون آمنا هنا عليك استخدام unsigned char اكتب، وهو النوع الوحيد الذي لا يحتوي على تمثيلات فخ. بالطبع، منصة مع محاصرة char يمكن أن تسعى بأمان "غريبة".

وفي الوقت نفسه، الخاص بك sizeof(a + 1) لا يبدو أن معنى. a + 1 هو تعبير عن int * اكتب. لماذا تريد استخدام حجم المؤشر لزيادة x القيمة في هذه الحالة ليست واضحة بالنسبة لي. ماذا كنت تحاول تحقيقه؟

أما لعدم وجود تحذيرات ... لن أتوقع من المترجم إصدار أي تحذيرات هنا. غالبا ما يحذر دول مجلس التعاون الخليجي من نوع إعادة تفسير الذاكرة AKA)، ولكن منذ ذلك الحين char يتم السماح بإعادة تفسير صراحة (كما قلت أعلاه)، لا يوجد تحذير هنا. علاوة على ذلك، تميل المصابيح الصريحة عادة إلى قمع أي تحذيرات، لأنها وسيلة لإخبار التحويل البرمجي الذي تريد فعله فعليا أن تفعل شيئا بغض النظر عن طريقة الخطأ و / أو الخطرة قد يكون.

نصائح أخرى

يلقي من أي نوع مؤشر إلى Char * يسمح صراحة بلغة C. لذلك معظم هذا جيد.

for(x=(char *)&b[0]; x <= (char *)&b[9][9]; x += sizeof(a+1))  

الجزء الأول جيد x = (char*)&b[0]; يحدد مؤشر تشار إلى بداية الصفيف. الاختبار جيد أيضا x <= (char *)&b[9][9] سيكون صحيحا طالما نقاط X داخل الصفيف.

x += sizeof(a+1) هو الجزء iffy. على الأكثر 32 بت معهد وحدة المعالجة المركزية Sizeof (int *) فقط يحدث أن تكون نفس المقايف (int)، لذلك ربما هذا الرمز الشغل, ، ولكن فقط عن طريق الصدفة.

أنا متأكد من ما كان المقصود كان x += sizeof(a[0]) أو x += sizeof(b[0]), ، ولكن نظرا لأن القانون فعل بالفعل ما كان المقصود، لم يلاحظ أحد الأخطاء.

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