C أنواع غير متوافقة في المهمة ، مشكلة مع المؤشرات؟

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

  •  24-09-2019
  •  | 
  •  

سؤال

مرحبًا ، أنا أعمل مع C ولدي سؤال حول تعيين مؤشرات.

struct foo
{
   int _bar;
   char * _car[SOME_NUMBER]; // this is meant to be an array of char * so that it can hold pointers to names of cars
}

int foofunc (void * arg)
{
   int bar;
   char * car[SOME_NUMBER];

   struct foo * thing = (struct foo *) arg;

   bar = thing->_bar; // this works fine
   car = thing->_car; // this gives compiler errors of incompatible types in assignment
}

Car و _car لديهما نفس الإعلان ، فلماذا أحصل على خطأ بشأن الأنواع غير المتوافقة؟ أظن أنه له علاقة مع كونهم مؤشرات (لأنهم مؤشرات على صفائف Char *، أليس كذلك؟) لكنني لا أرى لماذا هذه مشكلة.

عندما أعلنت char * car; بدلاً من char * car[MAXINT]; يجمع بشكل جيد. لكنني لا أرى كيف سيكون ذلك مفيدًا بالنسبة لي لاحقًا عندما أحتاج إلى الوصول إلى معلومات معينة باستخدام الفهرس ، سيكون من المزعج للغاية الوصول إلى هذه المعلومات لاحقًا. في الواقع ، لست متأكدًا مما إذا كنت سأذهب بالطريقة الصحيحة ، فربما يكون هناك طريقة أفضل لتخزين مجموعة من الأوتار بدلاً من استخدام مجموعة من char *؟

تحرير: لم أقصد استخدام int_max (القيمة القصوى لـ int) ، إنها مجرد int أخرى ، والتي تبلغ حوالي 20.

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

المحلول

أنت تقوم بإنشاء مجموعة جديدة من maxint الحجم. أعتقد أنك تريد إنشاء مؤشر لمجموعة من MaxInt الحجم.

إنشاء مؤشر لمجموعة من char*s:

فيما يلي مجموعة من الحجم الأقصى لعناصر char*:

char * car[MAXINT]; 

ما يلي هو مؤشر ل: مجموعة من الحجم maxint إلى char* عناصر:

char* (*car)[MAXINT];

فيما يلي كيف تقوم بتعيين مؤشر على: مجموعة من Maxint Size to Char* العناصر:

char* (*car)[MAXINT];
car = &arg->_car;

أخطاء بناء الجملة الأخرى في السؤال:

  • يجب أن يكون لديك فاصلة فاصلة بعد تعريف الهيكل الخاص بك.
  • يجب أن تستخدم foo* ليس foo. لذلك ينبغي أن يكون:
    struct foo* thing = (struct foo *) arg;
  • يجب أن تستخدم thing ليس arg:
    bar = thing->_bar;
    car = thing->_car;

نصائح أخرى

car و _car كلا المصفوفتين ، ولا يمكنك تعيين المصفوفات في C (باستثناء عندما يتم تضمين الصفيف في هيكل (أو اتحاد) وأنت تقوم بتعيين هيكل).

كما أنها صفائف من المؤشرات إلى Char ، بدلاً من مؤشرات إلى صفائف Char. ما كتبته في الرمز هو ما تريده على الأرجح - يمكنك تخزين المؤشرات إلى أسماء Maxint في الصفيف. ومع ذلك ، يجب أن تصف النوع بشكل صحيح - كمجموعة من المؤشرات إلى مؤشرات char أو char.

سيبدو مؤشر لمجموعة من الشخصيات:

char (*car)[MAXINT];

ونقطة إلى مجموعة من مؤشرات الشخصية (شكرًا ، براين) ستبدو:

char *(*car)[MAXINT];

كن حذرا من maxint. يمكن أن يكون هذا صفيفًا كبيرًا جدًا (على Linux ، <values.h> تعريف MAXINT مثل INT_MAX, ، وهو على الأقل 231-1).


الرمز يشبه:

struct foo
{
   int _bar;
   char * _car[MAXINT];
}

int foofunc (void * arg)
{
   int bar;
   char * car[MAXINT];
   struct foo thing = (struct foo *) arg;
   bar = arg->_bar; // this works fine
   car = arg->_car; // this gives compiler errors of incompatible types in assignment
}

لا ينبغي تجميع المهمة إلى شريط ولا سيارة على الإطلاق - arg هو void *. من المفترض أن تهدف إلى استخدام thing في شكل أو شكل. كما لاحظ براين ، هناك مشاكل هناك أيضًا:

إما تريد:

int foofunc(void *arg)
{
    int bar;
    char *car[MAXINT];
    struct foo thing = *(struct foo *)arg;
    bar = thing._bar; // this works fine
    car = thing._car; // this is still an array assignment
    ...other code using bar and car...
}

أو تريد:

int foofunc(void *arg)
{
    int bar;
    char *car[MAXINT];
    struct foo *thing = (struct foo *) arg;
    bar = thing->_bar; // this works fine
    car = thing->_car; // this is still an array assignment
    ...other code using bar and car...
}

أو في الواقع:

int foofunc(void *arg)
{
    struct foo *thing = (struct foo *) arg;
    int bar           = thing->_bar; // this works fine
    char *car[MAXINT] = thing->_car; // this is still an array assignment
    ...other code using bar and car...
}

أخيرًا ، التعامل مع مهمة الصفيف ، في C يمكنك استخدامه بشكل معقول memmove() لفعل هذا:

int foofunc(void *arg)
{
    struct foo *thing = (struct foo *) arg;
    int bar           = thing->_bar; // this works fine
    char *car[MAXINT];
    memmove(car, thing->_car, sizeof(car));
    ...other code using bar and car...
}

وظيفة مماثلة memcpy() ليس لديها دلالات موثوقة إذا كانت المناطق التي يجب نسخها تتداخل ، في حين memmove() يفعل؛ من الأسهل استخدام دائمًا memmove() لأنه يعمل دائما بشكل صحيح. في C ++ ، يجب أن تكون حذرًا بشأن استخدامه memmove() (أو memcpy()). في هذا الرمز ، سيكون من الآمن بما فيه الكفاية ، ولكن فهم سبب عدم التافهة.

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

نقطة أخيرة - في الوقت الحالي: هل أنت متأكد من أنك بحاجة إلى الوسيطة إلى الوظيفة كملف void *؟ يفتح الرمز على جميع أنواع سوء المعاملة التي يمكن منعها إذا تم إعلان الوظيفة لأخذ ''struct foo *"بدلاً من ذلك (أو حتى أ"const struct foo *').

لا يمكنك التعيين إلى صفيف بالطريقة التي تفعله. يمكنك عمل نسخة من العناصر.

for(int i = 0; i < MAXINT; i++)
{
  car[i] = (arg->_car)[i]
}

لاحظ أنه إذا لم تكن الأوتار ثابتة ، فقد تحتاج إلى استخدام strcpy.

تدوين الصفيف في C أمر مربك بشكل شرعي ؛ الكود الخاص بك لا يعني ما تعتقد أنه يعني.

arg->_car يعني "عنوان الصفيف _car". بصورة مماثلة، car يعني "عنوان الصفيف car". إذا كنت تحاول نسخ محتويات _car للسيارة ، فإن هذا سيفعل ذلك:

memcpy(car, _car, MAXINT);

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

كنت تعلن ذلك مثل هذا:

#define CARSIZE 65
int numCars = 0;
char **car; /* a list of addresses, each one will point to a string */

لإضافة سيارة:

char *newCar = malloc(CARSIZE); /* make room */
strncpy(newCar, "Mercedes", CARSIZE); /* newCar has the address of the string */
car[numCars++] = newCar; /* store it */

لسرد السيارات:

int n;
for (n = 0; n < numCars; ++n)
    printf("%s\n", car[n]);

لإزالة السيارة في الموضع n:

free(car[n]); /* release the memory */
/* condense the list of pointers */
for ( ; n < numCars - 1; ++n)
    car[n] = car[n+1];

هذا روتيني تماما في C. ملاحظة: ما سبق خارج الجزء العلوي من رأسي ولم يتم نسخه من برنامج عمل ، لذلك لا يمكنني أن أعد كل ما في المكان المناسب. أظن أن هذه مهمة منزلية ، لذلك لا أريد أن أعطيك كل شىء...

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