سؤال

ولقد حصلت على التعليمات البرمجية التالية:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    cout << a << ", " << b << endl;
    return 0;
}

وهذا يجمع ويعمل، أي. طباعة bar, bar. الآن أود أن تثبت أن ما يجري هنا ليس نسخ السلسلة. وأود أن تغيير b وتبين أن a يتغير أيضا. خطرت لي هذا الرمز بسيط:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    b[1] = 'u'; // ← just this line added
    cout << a << ", " << b << endl;
    return 0;
}

... ولكنه خطأ التقسيم. لماذا ا؟ والشيء المثير للاهتمام هو أن التعديل التالي يعمل على ما يرام:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char b[] = "bar"; // ← declaration changed here
    a = b;
    b[1] = 'u';
    cout << a << ", " << b << endl;
    return 0;
}

لماذا لا segfault مثل سابقتها؟ أعتقد أنا في عداد المفقودين بعض الفرق المهم بين على غرار مؤشر والتهيئة سلسلة على غرار مجموعة.

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

المحلول

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

وانظر أيضا هذا السؤال: هل سلسلة حرفية في ج ++ التي تم إنشاؤها في ذاكرة ساكنة؟ .

نصائح أخرى

وعند كتابة هذا:

char *b = "bar";

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

و(رمز الخاص بك هو C ++، C لا، ولكن هذا غير ذي صلة على هذا السؤال).

وعندما تكتب:

char *foo = "bar";

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

ويمكن أن تظهر أيضا أن 'ا' تم تغيير عن طريق طباعة قيمة المؤشر.

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;

    cout << (void*)a << ", " << (void*)b << endl;
}

وهذا سيتم طباعة العنوان الذي "أ" و "ب" النقطة.
عليك أن يلقي إلى 'الفراغ * لأن طاقتها المشغل << ل' شار * لطباعة سلسلة وأي مؤشر آخر طباعة العنوان.

في نظرية، سلسلة حرفية لا ينبغي أن يكون قادرا على أن تسند إلى شار *، سوى "CONST شار *. ثم المترجم ستتوقف لكم قبل كتب SEG يخطأ التعليمات البرمجية.

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

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