هل يمكن/لماذا استخدام char * بدلاً من const char * في نوع الإرجاع يسبب الأعطال؟

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

  •  07-07-2019
  •  | 
  •  

سؤال

قرأت في مكان ما أنه إذا كنت تريد أن تقوم دالة C/C++ بإرجاع مصفوفة أحرف (على عكس std::string)، فيجب عليك إرجاع const char* بدلاً من char*.قد يؤدي القيام بهذا الأخير إلى تعطل البرنامج.

فهل يستطيع أحد أن يشرح هل هذا صحيح أم لا؟إذا كان هذا صحيحًا، فلماذا يعد إرجاع char* من دالة خطيرًا جدًا؟شكرًا لك.

const char * my_function()
{
    ....
}

void main(void)
{
    char x[] = my_function();
}
هل كانت مفيدة؟

المحلول

إذا كان لديك وظيفة وترجع "سلسلة حرفية" بعد ذلك لا بد من العودة شار CONST *. وهذه لا تحتاج إلى تخصيص على كومة من malloc لأنهم تجميعها في قسم للقراءة فقط من الملف القابل للتنفيذ نفسها.

مثال:

const char* errstr(int err)
{
    switch(err) {
        case 1: return "error 1";
        case 2: return "error 2";
        case 3: return "error 3";
        case 255: return "error 255 to make this sparse so people don't ask me why I didn't use an array of const char*";
        default: return "unknown error";
    }
}

نصائح أخرى

ما قيل لك هو لا حقيقي.

عودة أ const char * يمكنه تحسين دلالات الوظيفة (أيلا تعبث بما أعطيك) ولكن العودة أ char * على ما يرام تماما.

ومع ذلك، في كلتا الحالتين، أنت يجب تأكد من إرجاع أ char * أو const char * التي تم تخصيصها على الكومة في my_function (أي.المخصصة باستخدام malloc أو new)، وإلا كلما my_function يعود، والذاكرة ل [const] char * سيتم إلغاء التخصيص، وسوف تتمكن من الوصول إلى مؤشر غير صالح.

وأخيرا أنت يجب تذكر أن free أو delete ال [const] char * تم إرجاعه إليك بمجرد الانتهاء منه، وإلا فسوف تتسرب الذاكرة.أليست C/C++ لغات رائعة؟

لذلك، في C، سيكون لديك

const char *my_function() {
    const char *my_str = (const char *)malloc(MY_STR_LEN + 1);  // +1 for null terminator.
    /* ... */
    return my_str;
}

int main() {
    const char *my_str = my_function();
    /* ... */
    free(my_str);
    /* ... */
    return 0;
}

وعادة، وهذا ليس قضية، ولكن هناك أشياء للنظر فيها. انها عادة ما تكون مسألة CONST-صحة، وهو ما يعني مسار حفظ ما يمكنك تغيير وما لا يمكن.

إذا كنت إرجاع سلسلة مقتبسة مزدوجة، انها const char *، والتعامل معها مثل أي شيء آخر هو دعوة للمشكلة. تغيير مثل سلسلة هو السلوك غير معروف، ولكن سوف يسبب عادة البرنامج لتعطل أو تغيير هذه السلسلة أينما انها المشار إليها.

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

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

وليس هناك مشكلة فورية مع عودة الذاكرة المخصصة مع malloc() أو new، ولكن لديك مشكلة الملكية: ما وظيفة يجب أن free() / delete ذلك ومتى، وماذا تفعل حول نسخ الممكنة؟ هذا هو المكان الذي تألق مؤشرات الذكية C ++ الصورة.

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

وببساطة سوف تغيير رمز الإرجاع لا تسبب وقوع الحادث. ومع ذلك إذا كانت السلسلة عودتك هي ثابتة (على سبيل المثال return "AString")، يجب أن تعيد const char * للتأكد من أن المترجم بالكشف عن أي محاولة تعديل تلك الذاكرة التي <م> سوف المرجح أن يسبب وقوع الحادث. يمكنك بالتأكيد استخدام القوالب ومثل للالتفاف على الشيكات مترجم، ولكن في هذه الحالة عليك أن <م> العمل لجعل تحطم يحدث.

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