ما هو الفرق بين المؤشر والمصفوفة في السياق التالي؟

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

  •  20-08-2019
  •  | 
  •  

سؤال

#include <cstring>
int main()
    {
    char *pName = new char[10];
    char dummy[] = "dummy";
    strcpy(pName + 0,dummy);//how this is different from -->this works
    strcpy(pName[0],dummy);//this one...--> error C2664: 'strcpy' : 
                           //cannot convert parameter 1 
                           //from 'char' to 'char *'

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

المحلول

  • Pname [0] هو العنصر الأول في صفيف الأحرف (واحد حرف)
  • Pname هو اختصار لـ & pname [0] (مؤشر إلى العنصر الأول من صفيفك)

السبب في أنك تحصل على خطأك هو أن Strcpy يتوقع مؤشرًا إلى char (char*) ، وليس قيمة char (وهو ما هو pname [0])

نصائح أخرى

عند التعامل مع المؤشرات والمصفوفات في C أو C ++ ، فإنه يساعد حقًا على التعرف عليها على أنها بنيات متميزة للغاية (أعتقد أن أحد أفضل الكتب التي تشرح هذا التمييز هو كتاب بعنوان "Deep C Secrets" إذا كنت أتذكر بشكل صحيح). ما يزحر المياه هو حقيقة أن هناك تحويلًا صامتًا واحدًا مسموحًا به من أسماء الصفيف إلى المؤشرات (عدم الاتساق في معالجة اللغة مع الأسماء المتغيرة) - لكن من المهم للغاية عدم تفسير وجود ظاهرة الانحلال هذه على أنها تشير التكافؤ.

لمساعدتنا على التفكير في هذا ، دعونا نقدم فكرة "خلية الذاكرة". نحن نمثل "خلية الذاكرة" على أنها لها سمتين:

a) value
b) address

يمكننا بعد ذلك صياغة متغير C ++ بسيط باعتباره وجود سمتين (لا نحتاج إلى أنواع في هذا المستوى المنخفض من التجريد):

c) name  
d) memory cell

مثل معظم النماذج ، لديها بعض أوجه القصور (لا تتعامل مع صفيف مع أكثر من عنصر واحد ، لكنه يكفي لأغراضنا).

على سبيل المثال:

// non-array variable: name 'i', and memory cell: value=3, address=0x0A
int i = 3;

// non-array variable: name 'p', and memory cell: value=0x0A, address=0x0B
int *p = &i;

// array variable: name 'a', and memory cell: vale=4, address=0x0C     
int a[1] = { 4 };

// non-array variable: name 'b', and memory cell: value=0x0C, address = 0x0D
int (*b)[1] = &a;

// non-array variable: name 's', and memory cell: value=0x0C, address = 0x0E
int *s = &a[0];


// non-array variable: name 't', and memory cell: value=0x0C, address = 0x0F
int *t = a; // Here is the key difference! read on...

الآن هذا هو الفرق الرئيسي بين متغير الصفيف ومتغير C ++ غير (المؤشر) غير المؤشر:

عندما يتم تقييم اسم متغير في C ++ ، فإنه يقيم دائمًا على قيمة خلية الذاكرة الخاصة به مع استثناء واحد: إذا أسماء المتغير متغير صفيف.
إذا كان المتغير هو اسم صفيف يقوم بتقييمه إلى تبوك من خلية الذاكرة.
الخطان أعلاه يستحق القراءة مرة أخرى.

فيما يلي بعض الأمثلة للمساعدة في توضيح الآثار (راجع المتغيرات المذكورة أعلاه):

int k = i;  // the 'i' name evaluates to the value of its cell, so 'k' is set to 3

int *q = p; // 'p' evaluates to the value of its cell, so 'q' is set to 0x0A

int *r = a; // 'a' evaluates to the *address* of its cell, so 'r' is set to 0x0C

int (*c)[1] = b; // 'c' is set to 0x0D

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

لذلك على سبيل المثال لا تفعل هذا:

// myproj_file1.cpp
int array[100] = { 0 }; // here 'array' evaluates to the *address* of the first memory cell

// myproj_file2.cpp
extern int* array; // here 'array' evaluates to the *value* of the first memory cell 
            // Assuming the linker links the two
            // what it does if you read the assembly, is something like this: 
            // extern int* array = (int*) array[0];
            // but it doesn't have to, it can do anything, since the behavior is undefined

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

--
أنواع وظائف PS وأسمائها وتسوسها غير ذات صلة بمعظم هذا المنشور
ملاحظة: لقد تركت أيضًا عن قصد أن تحويل الصفيف إلى المؤشر لا يحدث عندما تكون المصفوفات مرتبطة بأنواع مرجعية

من الناحية الفنية ، strcpy(pName[0], dummy); ليس صحيحا. حتى لو تم تخصيص الذاكرة لذلك.

هذا بسبب pName[0] من النوع "char" بينما pName + 0 من النوع char*. كلاهما يشير إلى نفس الذاكرة ، ولكن بطرق مختلفة.

يمكن للمترجم أن يتحول بعد ذلك strcpy(pName[0], dummy); داخل strcpy((char*) pName[0], dummy); وهو طاقم ضمني خطير. إذا كان المترجم الخاص بك نصف لائق ، فستحصل على تحذير أو خطأ (كما ترى مع "خطأ C2664").

ليس هناك فرق. سيتعطل كلاهما نظرًا لعدم تخصيص أي مساحة لـ Pname. :) [تحرير: لم يعد تحطمًا - تم تحرير سؤال

الفرق الرئيسي هو الفرق الأنيق ، الذي يتأثر بشكل متكرر والذي يناسب الطريقة التي يتم بها كتابة الكود المحيط - في الغالب وصول الصفيف أو الوصول إلى المؤشر في الغالب.

(تحرير: على افتراض أنك تعني حقًا & pname [0] كما أشار براين بوندي.)

الصفيف هو ببساطة مؤشر تلقائيًا (عادة) تم تعيينه إلى كتلة ذاكرة مخصصة تلقائيًا. أخذ مثالك ، يمكنك إعلان الدمية على قدم المساواة على أنها:

char    dummy[] = "dummy";
char    *dummy = "dummy";

ويمكنك بعد ذلك استخدام بناء جملة الصفيف أو بناء جملة المؤشر للوصول إلى البيانات:

char    ch = dummy[0];   // get the first element of the array
char    ch = *dummy;     // get the data pointed to by dummy

كلاهما [] و * يمكن استخدام مؤشرات وصفائف إعادة تكرار DE ، وبالتالي فإن ما يلي مكافئ:

array[N];
*(ptr + N);

بالنظر إلى النموذج الثاني ، (ptr + N) لا يزال مؤشر ، فقط على طول الصفيف. هذا هو السبب في أنه صحيح في مثالك. ptr[N] هو إلغاء مراجع المؤشر وهو شار (في هذا السياق).

Pname هو مؤشر للذاكرة المخصصة حديثًا. char *pName = new char[10];

الدمية هي أيضا صفيف/مؤشر. char dummy[] = "dummy";

PNAME هو مؤشر ويشير إلى العنوان الأساسي ، حتى أنك لا تزال (PNAME + 0) لا تزال تشير إلى نفس موقع الذاكرة ، لأن إضافتك الوحيدة. strcpy(pName + 0,dummy);

strcpy استخدم متغير مؤشر ، وقيمة المرور الخاصة بك في الوسيطة الأولى ، وبالتالي تحصل على خطأ strcpy(pName[0],dummy)

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