سؤال

عند تجميع الكود التالي:

void DoSomething(int Numbers[])
{
    int SomeArray[] = Numbers;
}

يشكو مترجم VS2005 من الخطأ C2440:'جار تهيئة' :لا يمكن التحويل من "int []" إلى "int []"

أفهم أنه في الحقيقة يحاول توجيه مؤشر إلى مصفوفة لن تعمل.ولكن كيف تفسر الخطأ لشخص يتعلم C++؟

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

المحلول

هناك ثلاثة أشياء تحتاج إلى شرحها للشخص الذي تحاول مساعدته:

  1. لا يمكن تمرير المصفوفات حسب القيمة إلى دالة في C++. للقيام بما تحاول القيام به، تحتاج إلى تمرير عنوان بداية المصفوفة إلى DoSomething(), ، وكذلك حجم المصفوفة بشكل منفصل int (حسنًا، size_t, ، لكنني لن أزعج نفسي بقول ذلك) حجة.يمكنك الحصول على عنوان بداية بعض المصفوفات myArray مع التعبير &(myArray[0]).نظرًا لأن هذا أمر شائع تريد القيام به، تتيح لك لغة C++ استخدام اسم المصفوفة فقط - على سبيل المثال. myArray - للحصول على عنوان العنصر الأول الخاص به.(وهو ما يمكن أن يكون مفيدًا أو مربكًا، اعتمادًا على الطريقة التي تنظر بها إلى الأمر.) ولجعل الأمور أكثر إرباكًا، تسمح لك لغة C++ بتحديد نوع المصفوفة (على سبيل المثال. int Numbers[]) كمعلمة لوظيفة، ولكنها تعامل سرًا مع تلك المعلمة كما لو أنها مُعلن عنها كمؤشر (int *Numbers في هذه الحالة) - يمكنك حتى القيام بذلك Numbers += 5 داخل DoSomething() لجعله يشير إلى مصفوفة تبدأ من المركز السادس!

  2. عندما تعلن عن متغير صفيف مثل SomeArray في C++، يجب عليك إما توفير حجم واضح أو "قائمة التهيئة", ، وهي عبارة عن قائمة قيم مفصولة بفواصل بين الأقواس.ليس من الممكن للمترجم أن يستنتج حجم المصفوفة بناءً على مصفوفة أخرى تحاول تهيئتها بها، لأن...

  3. لا يمكنك نسخ صفيف إلى آخر، أو تهيئة صفيف من آخر في C++. لذلك حتى لو كانت المعلمة Numbers كان في الواقع مصفوفة (على سبيل المثال بحجم 1000) وليس مؤشرًا، وقمت بتحديد حجم SomeArray (مرة أخرى كما يقول 1000)، السطر int SomeArray[1000] = Numbers; سيكون غير قانوني.


لتفعل ما تريد أن تفعله فيه DoSomething(), ، اسأل نفسك أولاً:

  1. هل أحتاج إلى تغيير أي من القيم في Numbers?
  2. إذا كان الأمر كذلك، فهل أريد منع المتصل من رؤية هذه التغييرات؟

إذا كانت الإجابة على أي من السؤالين هي "لا"، فلن تحتاج في الواقع إلى عمل نسخة منه Numbers في المقام الأول -- فقط استخدمه كما هو، ولا تنس إنشاء قسم منفصل SomeArray مجموعة مصفوفة.

إذا كانت الإجابة على كلا السؤالين هي "نعم"، فستحتاج إلى عمل نسخة منها Numbers في SomeArray والعمل على ذلك بدلا من ذلك.في هذه الحالة، عليك أن تفعل حقا SomeArray سي ++ vector<int> بدلاً من مصفوفة أخرى، لأن هذا يبسط الأمور حقاً.(اشرح فوائد المتجهات مقارنة بالتخصيص اليدوي للذاكرة الديناميكية، بما في ذلك الحقائق التي تفيد بأنها يستطيع سيتم تهيئتها من صفائف أو نواقل أخرى، وسوف تستدعي منشئي العناصر عند الضرورة، على عكس النمط C memcpy().)

نصائح أخرى

ويقول أن هناك أنواع وأنواع غير مكتملة:

struct A;

هل نوع غير كامل من البنية دعا A. بينما

struct A { };

هل من نوع كاملة من البنية دعا A. حجم أولا ليست معروفة بعد، في حين يعرف حجم الثانية.

وهناك أنواع الطبقة ناقصة مثل البنية المذكورة أعلاه. ولكن هناك أيضا أنواع مجموعة غير مكتملة:

typedef int A[];

وهذا هو نوع مصفوفة ناقصة دعا A. حجمها لم يعرف بعد. لا يمكنك إنشاء مجموعة للخروج منه، لأن المترجم لا يعرف كيف كبيرة هي مجموعة. ولكن يمكنك أن <م> استخدام لإنشاء مجموعة، <م> فقط إذا كنت تهيئة ذلك على الفور:

A SomeArray = { 1, 2, 3 };

والآن، المترجم يعرف مجموعة هي مجموعة كثافة العمليات مع 3 عناصر. إذا حاولت تهيئة مجموعة مع مؤشر، فإن المترجم لن يكون هناك أي أكثر ذكاء من ذي قبل، وترفض، لأن ذلك لن تعطيه حجم المصفوفة المراد إنشاؤه.

في محاولة لجعل رسالة خطأ أكثر فائدة، والمترجم هو في الواقع أشياء مربكة. على الرغم من أن يتم تعريف المعلمة Numbers كما صفيف، C / C ++ لا (لا يمكن) فعلا تمرير صفيف - المعلمة Numbers هو في الواقع مؤشر

وهكذا الخطأ حقا أن يقول "cannot convert from 'int *' to 'int []'"

ولكن بعد ذلك سيكون هناك ارتباك - "مهلا، ليس هناك int* تشارك في التعبير"، قد يقول شخص ما

.

لهذا السبب هو حقا أفضل لتجنب المعلمات مجموعة - أعلن بأنها مؤشرات، لأن هذا هو ما كنت حقا الحصول على أي حال. والتفسير لشخص تعلم C / C ++ يجب تثقيفهم على حقيقة أن المعلمات مجموعة هي الخيال - انهم حقا المؤشرات

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

في هذه الحالة، ربما كنت تبدأ مع شيء من هذا القبيل:

<اقتباس فقرة>   

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

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

ولعل الجواب يمكن أن يكون، "لأن المترجم لا يعرف كيف كبيرة هي مجموعة".

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

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