سؤال

أريد وظيفة بسيطة تستقبل سلسلة وترجع مجموعة من السلاسل بعد بعض التحليل.إذن، هذا هو توقيع وظيفتي:

int parse(const char *foo, char **sep_foo, int *sep_foo_qty) {
    int i;
    char *token;
    ...
    strcpy(sep_foo[i], token); /* sf here */
    ...
}

ثم أسميها هكذا:

char sep_foo[MAX_QTY][MAX_STRING_LENGTH];
char foo[MAX_STRING_LENGTH];
int sep_foo_qty, error;

...

error = parse(foo, sep_foo, &sep_foo_qyt);

...

بهذه الطريقة أحصل على تحذير أثناء التجميع:

warning: passing argument 2 of 'parse' from incompatible pointer type

ثم حدث خطأ تجزئة أثناء التنفيذ في السطر المميز بـ /* sf هنا */

ما هو الخطأ في رمز C الخاص بي؟

شكرا لك مقدما

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

المحلول

التحذير صحيح تماما.وظيفتك تريد مجموعة من المؤشرات.أنت تعطيه مجموعة من المصفوفات.

مُتوقع:

 sep_foo:
 +------+       +-----+
 |char**|--> 0: |char*|-->"string1"
 +------+       +-----+
             1: |char*|-->"string2"
                +-----+
*sep_foo_qty-1: |...  |
                +-----+

ما قدمته:

           sep_foo:
           +--------------------------------+
        0: | char[MAX_STRING_LENGTH]        |
           +--------------------------------+
        1: | char[MAX_STRING_LENGTH]        |
           +--------------------------------+
MAX_QTY-1: | ...                            |
           +--------------------------------+

مصفوفة تحتوي على عناصر من النوع X يمكن أن "تتحلل" إلى مؤشر إلى-X, ، أو X*.ولكن قيمة X لا يسمح بالتغيير في هذا التحويل.فقط واحد يسمح بعملية الاضمحلال.كنت في حاجة إلى أن يحدث مرتين.في حالتك، X هو مجموعة من-MAX_STRING_LENGTH-الحرف.الوظيفة تريد X ليكون المؤشر إلى شار.وبما أن هذه ليست هي نفسها، فإن المترجم يحذرك.أنا مندهش بعض الشيء لأنه كان مجرد تحذير لأنه لا يمكن أن يأتي أي شيء جيد مما سمح المترجم بحدوثه.

في وظيفتك، يمكنك كتابة هذا الكود:

char* y = NULL;
*sep_foo = y;

هذا هو القانون القانوني منذ ذلك الحين sep_foo هو char**, ، لذا *sep_foo هو char*, ، وذلك هو y;يمكنك تعيينهم.ولكن مع ما حاولت القيام به، *sep_foo لن حقًا يكون أ char*;سيكون يشير إلى مجموعة من char.في الواقع، سيحاول الكود الخاص بك القيام بذلك:

char destination[MAX_STRING_LENGTH];
char* y = NULL;
destination = y;

لا يمكنك تعيين مؤشر إلى مصفوفة، ولذلك يحذر المترجم من أن الاستدعاء ليس جيدًا.

هناك طريقتان لحل هذا:

  • غيّر طريقة إعلانك وتخصيصك sep_foo على جانب الاتصال بحيث يتطابق مع ما تتوقع الوظيفة تلقيه:

    char** sep_foo = calloc(MAX_QTY, sizeof(char*));
    for (int i = 0; i < MAX_QTY; ++i)
      sep_foo[i] = malloc(MAX_STRING_LENGTH);
    

    أو مكافئ

    char* sep_foo[MAX_QTY];
    for (int i = 0; i < MAX_QTY; ++i)
      sep_foo[i] = malloc(MAX_STRING_LENGTH);
    
  • قم بتغيير النموذج الأولي للوظيفة لقبول ما تقدمه لها بالفعل:

    int parse(const char *foo, char sep_foo[MAX_QTY][MAX_STRING_LENGTH], int *sep_foo_qty);
    

نصائح أخرى

ويجب أن تكون المعلمة 2

char sep_foo[][MAX_STRING_LENGTH]

لتوضيح، يتم تمرير مؤشر إلى تحليل () والتعامل معها على أنها مؤشر إلى مؤشر. وهناك مجموعة متعددة الأبعاد في C ليست مجموعة من المؤشرات. بل هو كتلة واحدة من الذاكرة المشار إليه بواسطة متغير صفيف. لا يمكنك dereference مرتين.

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

(assume MAX_STRING_LENGTH = 16, MAX_QTY = 2)
sep_foo       = &&0000
sep_foo[0]    =  &0000
sep_foo[0][0] = *&0000 = 12
sep_foo[0][8] = *&0008 = 74
sep_foo[1]    =  &0010
sep_foo[1][0] = *&0010 = 12


0000  12 34 56 78  9A BC DE F0  74 10 25 89  63 AC DB FE
0010  12 34 56 78  9A BC DE F0  74 10 25 89  63 AC DB FE

ولكن، وظيفة الخاص بك وتتوقع مجموعة من المؤشرات (في الواقع، مؤشر إلى مؤشر). وعلى غرار هذا على هذا النحو:

sep_foo_arg       =   &&0000
sep_foo_arg[0]    =  *&&0000 = &0010
sep_foo_arg[0][0] =  *&*&0000 = 12
sep_foo_arg[0][8] = *(&*&0000 + 8) = 74
sep_foo_arg[1]    =  *&&0002 = &0020
sep_foo_arg[1][0] = *&*&0000 = 12

0000  0010 0020  xxxx xxxx  xxxx xxxx  xxxx xxxx

0010  12 34 56 78  9A BC DE F0  74 10 25 89  63 AC DB FE
0020  12 34 56 78  9A BC DE F0  74 10 25 89  63 AC DB FE

نعم ... بناء الجملة قد يكون مربكا بعض الشيء عن تفسيرات بلدي ...

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

int parse(const char *foo, char (*sep_foo)[MAX_STRING_LENGTH], int *sep_foo_qty);

وإذا كان هذا هو رمز بك على وجه الدقة، ثم أنا التخمين segfault لأن من حقيقة أنك لم يخصص الذاكرة إلى char* token داخل وظيفة تحليل الخاص بك، ومن ثم استخدام ذلك في strcpy الخاص بك.

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