سؤال

كيف يمكنني كتابة الكود الخاص بي إلى مثال فهرس صفيف محدد لمجموعة يحدث ليكون عضوًا في هيكل؟ الرمز التالي يعطيني مشاكل.

// main.c

void clean_buffers(void); // prototype

struct DEV_STATUS {
    unsigned char ADDR;
    unsigned char DEV_HAS_DATA;
    unsigned char ETH_HAS_DATA;
    unsigned char DATA[20];
};

struct DEV_STATUS g_cmdQueue[60] = {0};

void main(void) {

    clean_buffers();

    while (1) {
        ;// MCU tasks        
    }
}

void clean_buffers(void) {
    unsigned char theCount = 0;
    byte queIdx;
    for (queIdx = 0; queIdx < 59; queIdx++) {
        struct DEV_STATUS *p_struct;
        unsigned char *p_data;
        p_struct = &g_cmdQueue[queIdx];
        p_data = &p_struct->DATA;
        p_struct->ADDR = 0;
        p_struct->DEV_HAS_DATA = 0;
        p_struct->ETH_HAS_DATA = 0;
        theCount = 0;
        while(*(p_data+theCount) != 0) {
            *(p_data+(theCount++)) = 0;
        }
    }    
} // EOF main.c

أحصل على خطأ في المترجم "هيكل/عضو الاتحاد المتوقع" على السطر التالي:

p_data = &p_struct->DATA;

كيف يجب أن أكتب مؤشرًا إذا أردت الوصول ، على سبيل المثال ، القيمة المحددة لبيانات عضو الهيكل [3]؟ أنا في حيرة من أمري ، اعتقدت أن البيانات p_data = & p_struct-> ؛ تم تعريفه ، يجب أن أكون قادرًا على الحصول عليه باستخدام *(PDATA+3) ولكن أعتقد أنني أفتقد شيئًا ما.

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

المحلول

هل أنت متأكد من أنك تقوم بتجميع نفس الرمز الذي نشرته هنا؟

إذا كان المترجم الخاص بك يشكو في هذا الخط

p_data = &p_struct->DATA;

من خلال رسالة "متوقعة للبنية/الاتحاد" ، من المحتمل أن يتم كسر المترجم الخاص بك.

لاحظ أن &p_struct->DATA هو تعبير صحيح تمامًا في C. لا يوجد أي مشاكل على الإطلاق في هذا التعبير في حد ذاته.

المشكلة هنا هي أن هذا ليس ما تحتاجه في قضيتك. &p_struct->DATA إرجاع مؤشر إلى صفيف "بيانات" بأكمله ، أي مؤشر من النوع unsigned char (*)[20]. أنت تحاول تعيين هذه القيمة إلى مؤشر من النوع unsigned char *. هذا غير قانوني في C ، لأن الأنواع مختلفة تمامًا ، ولكن تقليديًا استجابوا للمترجمين C بتحذير "عدم تطابق النوع" وأجرى تحويلًا ضمنيًا (والذي يعني ، راجع للشغل ، أن الكود الأصلي ، وإن كان "قذرًا" لا تزال تعمل على النحو المقصود).

حتى إذا قرر بعض البرمجيات الإبلاغ عن هذا عدم التطابق كخطأ (وهو أمر جيد) ، فلا يزال يتعين عليه الشكوى من أي مشاكل من نوع "هيكل/الاتحاد عضو". لا توجد مثل هذه المشاكل هنا.

ملاحظة كما قال آخرون بالفعل ، ما تحتاجه حقًا هو p_data = &p_struct->DATA[0], ، لكن هذا لا يزال لا يفسر سلوك المترجم الغريب. هل يمكن أن يكون "البيانات" هو ماكرو محدد في مكان ما قبل تعريف "Clean_Buffers"؟

تمت إضافة 10/19/2009: Nate ، في الكود الخاص بك يمكنك الوصول إلى صفيفك باستخدام فهرس theCount. نظرًا لأنك تستخدم وصول الفهرس على أي حال ، فلا يوجد سبب لإنشاء المؤشر الذي تحاول إنشاؤه. سيعمل الرمز بشكل جيد تمامًا دون أي مؤشر إضافي ، فقط DATA الحقل مباشرة

theCount = 0;
while (p_struct->DATA[theCount] != 0) {
  p_struct->DATA[theCount++] = 0;

(ربما كنت أستخدم ملف for دورة هنا).

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

p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
theCount = 0;
while (p_data[theCount] != 0) {
  p_data[theCount++] = 0;

علاوة على ذلك ، يمكنك اختيار متغير أكثر "غريبة" :)

unsigned char (*p_data)[20]; /* <- note: declared differently */
...
p_data = &p_struct->DATA; /* <- note: your original version */
...
theCount = 0;
while ((*p_data)[theCount] != 0) {
  (*p_data)[theCount++] = 0;

ومع ذلك ، العودة إلى أ unsigned char *p_data الإصدار ، نظرًا لأنك تقوم بإنشاء هذا المؤشر ، فقد يكون من المنطقي استخدام تقنية "مؤشر منزلق" بدلاً من استخدام الوصول إلى الفهرس

unsigned char *p_data;
...
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
while (*p_data != 0) {
  *p_data++ = 0;

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

نصائح أخرى

تفقد & في p_data = &p_struct->DATA;

p_struct هو بالفعل مؤشر. بعد ذلك ، استخدم p_data [] للوصول إلى صفيفك.

ما يجب أن تكتبه هو أحد شيئين:

p_data = p_struct->DATA; // DATA is the address of the first element.

أو

p_data = &p_struct->DATA[0]; // taking the address of the first element.

ما عليك سوى إزالة & في البداية ، مثل هذا:

p_data = p_struct->DATA;

هذا هو sintax خاص للمصفوفات (تذكر أنه يتم تمريره دائمًا كمرجع) وهو ما يعادل:

p_data = &p_struct->DATA[0];

ونعم ، يمكنك الآن استخدام *(PDATA+3)

أتمنى أن يساعد ذلك.

أُووبس! شكرا لك أندريه

struct dev_status *p_struct ؛ char غير موقعة *p_data ؛ p_struct = & g_cmdqueue [queidx] ؛ p_data = & p_struct-> data ؛

p_struct هو مؤشر ل struct DEV_STATUS.
&p_struct هو عنوان المؤشر إلى struct DEV_STATUS (أو مؤشر إلى مؤشر إلى struct DEV_STATUS).

ربما تريد تغيير هذا الخط إلى

    p_data = p_struct->DATA;

أوه ... الخاص بك clean_buffers() الوظيفة لا "تنظيف" العنصر g_cmdQueue[59].

ولأنه كائن عالمي ، المصفوفة g_cmdQueue تتم تهيئته إلى جميع الأصفار حتى قبل البيان الأول لـ main() exceepts.

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