قم بتغيير المؤشر إلى صفيف للحصول على عنصر صفيف محدد

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

  •  01-07-2019
  •  | 
  •  

سؤال

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

سؤالي هو التالي:

إذا كنت سأستخدم cout << &p, سيعرض "موقع الذاكرة الافتراضية" الخاص بالملف p.هل هناك طريقة يمكنني من خلالها التعامل مع "موقع الذاكرة الافتراضية" هذا؟

على سبيل المثال، يظهر التعليمة البرمجية التالية مجموعة من intس.

إذا أردت أن أظهر قيمة p[1] وكنت أعرف "موقع الذاكرة الافتراضية" لـ p, ، هل يمكنني أن أفعل بطريقة أو بأخرى "&p + 1" والحصول على قيمة p[1] مع cout << *p, ، والذي سيشير الآن إلى العنصر الثاني في المصفوفة؟

int *p;
p = new int[3];

p[0] = 13;
p[1] = 54;
p[2] = 42;
هل كانت مفيدة؟

المحلول

بالتأكيد، يمكنك التعامل مع المؤشر للوصول إلى العناصر المختلفة في المصفوفة، ولكنك ستحتاج إلى التعامل مع محتوى المؤشر (أي.عنوان ما يشير إليه p)، بدلاً من عنوان المؤشر نفسه.

int *p = new int[3];
p[0] = 13;
p[1] = 54;
p[2] = 42;

cout << *p << ' ' << *(p+1) << ' ' << *(p+2);

كل إضافة (أو طرح) تعني العنصر اللاحق (السابق) في المصفوفة.إذا كان p يشير إلى متغير 4 بايت (على سبيل المثال. كثافة العمليات على أجهزة الكمبيوتر النموذجية 32 بت) على العنوان 12345، سيشير p+1 إلى 12349، وليس 12346.لاحظ أنك تريد تغيير قيمة ما يحتوي عليه p قبل إلغاء الرجوع إليه للوصول إلى ما يشير إليه.

نصائح أخرى

ليس تماما. &p هو العنوان من المؤشر p. &p+1 سوف تشير إلى عنوان وهو واحد int* أبعد من ذلك.ما تريد القيام به هو

p=p+1; /* or ++p or p++ */

الآن عندما تفعل

cout << *p;

سوف تحصل على 54والفرق هو، p يحتوي على عنوان بداية مجموعة ints, ، بينما &p هل عنوان ص.لنقل عنصر واحد على طول، تحتاج إلى الإشارة إلى مزيد من داخل مجموعة كثافة العمليات, ، وليس على طول المكدس الخاص بك، حيث p الأرواح.

لو كان لديك فقط &p فإنك ستحتاج إلى القيام بما يلي:

int **q = &p; /* q now points to p */
*q = *q+1;
cout << *p;

سيؤدي ذلك أيضًا إلى إخراج 54 إذا لم أكن مخطئًا.

لقد مر وقت طويل (سنوات عديدة) منذ أن عملت مع المؤشرات ولكني أعلم أنه إذا كانت p تشير إلى بداية المصفوفة (أي.p[0]) وقمت بزيادته (أيp++) فإن p سيشير الآن إلى p[1].

أعتقد أنه يتعين عليك إلغاء الإشارة p للوصول إلى القيمة.يمكنك إلغاء الإشارة إلى المؤشر عن طريق وضع علامة * أمامه.

إذن *p = 33 مع تغيير p[0] إلى 33.

أعتقد أنك ستستخدم *(p+1) للحصول على العنصر الثاني، وبالتالي فإن بناء الجملة الذي تحتاجه سيكون:

cout << *(p+1)

أو

cout << *(++p)

أحب أن أفعل هذا:

&p[1]

بالنسبة لي يبدو أكثر أناقة.

فكر في "أنواع المؤشرات" في C وC++ على أنها تضع علامة منطقية طويلة جدًا صف من الخلايا يتم فرضه على البايتات الموجودة في مساحة ذاكرة وحدة المعالجة المركزية، بدءًا من البايت 0.يعتمد عرض كل خلية بالبايت على "نوع" المؤشر.يضع كل نوع مؤشر صفًا بعروض خلايا مختلفة.أ "int *" يضع المؤشر صفًا من الخلايا ذات 4 بايت، نظرًا لأن عرض تخزين int هو 4 بايت.أ "double *" يضع صفًا من 8 بايت لكل خلية؛أ "struct foo *" يضع المؤشر صفًا بحيث تكون كل خلية بعرض خلية واحدة "struct foo", ، أيا كان ذلك."عنوان" أي "شيء" هو إزاحة البايت، بدءًا من 0، للخلية الموجودة في الصف الذي يحتوي على "الشيء".

يعتمد حساب المؤشر على الخلايا الموجودة في الصف، وليس على البايتات. "*(p+10)" هو إشارة إلى الخلية العاشرة بعد "p"، حيث يتم تحديد حجم الخلية حسب نوع p.إذا كان نوع "p" هو "int"، فإن عنوان "p+10" هو 40 بايت بعد p؛إذا كان p مؤشرًا إلى بنية طولها 1000 بايت، فإن "p+10" يكون 10000 بايت بعد p.(لاحظ أن المترجم عليه اختيار الحجم الأمثل للبنية التي قد تكون أكبر مما تعتقد؛ويرجع ذلك إلى "الحشو" و"المحاذاة".قد تستغرق بنية 1000 بايت التي تمت مناقشتها في الواقع 1024 بايت لكل خلية، على سبيل المثال، لذا فإن "p+10" ستكون في الواقع 10240 بايت بعد p.)

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