سؤال

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

int wordncmp(char *p, char* q)
{   int n = k;
    for ( ; *p == *q; p++, q++)
        if (*p == 0 && --n == 0)
            return 0;
    return *p - *q;
}

int sortcmp(char **p, char **q)
{   return wordncmp(*p, *q);
}
...

qsort(word, nword, sizeof(word[0]), sortcmp);

هل هذا هو الحل؟

int sortcmp(const void *p, const void *q)
{   return wordncmp(* (char * const *) p, * (char * const *) q);
}
هل كانت مفيدة؟

المحلول

من المحتمل أن يعمل نموذج التعليمات البرمجية الأول مع أي مترجم ووحدة معالجة مركزية تقريبًا؛ومع ذلك، فهو سلوك غير محدد من الناحية الفنية، إذا اتبعت معيار C حرفيًا.

كما قلت، الحجة الأخيرة ل qsort() هو مؤشر إلى دالة تأخذ وسيطتين من النوع const void*. sortcmp يأخذ حجج مختلفة.المترجم الخاص بك يجب أعطيك تحذيرًا بشأن توقيعات النوع غير المتوافقة أو شيء من هذا القبيل.على أية حال، يتم إجراء عملية تحويل من وظيفة من نوع إلى وظيفة من نوع آخر.

يحدد معيار C أنه يمكنك إرسال مؤشرات دالة إلى مؤشرات دالة أخرى بأنواع مختلفة، ولكن لا يمكنك إلغاء الإشارة إلى مؤشر الدالة المصبوب واستدعاءه.ومع ذلك، إذا قمت بإعادة إرسال مؤشر الدالة مرة أخرى إلى نوعه الأصلي، فإن الاتصال الذي له سلوك محدد - فإنه يستدعي الوظيفة الأصلية.

نظرًا لأنك تقوم بالصب من أ int (*)(char**, char**) إلى أ int (*)(const void*, const void*), ، ثم في النهاية qsort() يقوم باستدعاء وظيفة المقارنة الخاصة بك دون إعادتها إليها int (*)(char**, char**), ، هذا سلوك غير محدد.

ومع ذلك، نظرًا لأنه في جميع البنى تقريبًا، أ char ** و أ const void* يتم تمثيلها بنفس الطريقة، فإن استدعاء الوظيفة سيعمل دائمًا إلى حد كبير.

إذا كنت ترغب في الحصول على سلوك محدد، فيجب عليك التأكد من أن وظيفة المقارنة الخاصة بك تحتوي على توقيع النوع المناسب، ومن ثم يمكنك تحويل الوسائط إلى النوع المناسب.الحل الخاص بك صحيح تمامًا ولا ينتهك معيار C هناك.أحسنت على const- الصواب - الكثير من الناس لا يفهمون ما هو بالضبط char * const * وسائل.

يجب عليك أيضا أن تجعل wordncmp() اتخاذ المعلمات من const char*, ، نظرًا لأنك لا تقوم بتعديل المعلمات.

ملاحظة جانبية:لا يمكنك أيضًا من الناحية الفنية إرسال مؤشر دالة إلى مؤشر بيانات (على سبيل المثال.أ void*) أو العكس.يسمح المعيار لمؤشرات الوظائف ومؤشرات البيانات بأن يكون لها أحجام مختلفة.حتى لو كان يعمل على جهاز الكمبيوتر الخاص بك، فليس من المضمون أن يعمل دائمًا.

نصائح أخرى

كلامك صحيح التوقيع sortcmp لا يتطابق مع ما qsort يتوقع.تصحيحك في محله wordcmp وينبغي أيضا أن يتم const- صحيح لأنك تفقد من الناحية الفنية بعضًا من const-ness على طول الطريق.

int wordncmp(const char *p, const char* q)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top