Domanda

Voglio una semplice funzione che riceve una stringa e restituisce una matrice di stringhe dopo un po 'di analisi. Quindi, questa è la mia firma della funzione:

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

Quindi lo chiamo così:

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);

...

In questo modo ricevo un avviso durante la compilazione:

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

E poi un errore di segmentazione durante l'esecuzione nella riga contrassegnata con / * sf qui * /

Cosa c'è di sbagliato nel mio codice C?

Grazie in anticipo

È stato utile?

Soluzione

L'avviso è esattamente giusto. La tua funzione vuole una serie di puntatori. Gli stai dando una serie di array.

atteso:

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

Cosa hai fornito:

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

Un array con elementi di tipo X può " decadimento " in un puntatore a - X* o MAX_STRING_LENGTH. Ma il valore di sep_foo non può cambiare in quella conversione. È consentita solo un'operazione di decadimento una . Avresti bisogno che accada due volte. Nel tuo caso, char** è un array di - *sep_foo - caratteri. La funzione vuole che char* sia puntatore a carattere. Dal momento che quelli non sono gli stessi, il compilatore ti avverte. Sono un po 'sorpreso che fosse solo un avvertimento poiché nulla di buono può venire da ciò che il compilatore ha permesso di accadere.

Nella tua funzione, puoi scrivere questo codice:

char* y = NULL;
*sep_foo = y;

Questo è un codice legale poiché y è un <=>, quindi <=> è un <=>, e così è anche <=>; puoi assegnarli. Ma con quello che hai provato a fare, <=> non sarebbe veramente essere <=>; indicherebbe un array di caratteri. Il tuo codice, in effetti, tenterebbe di farlo:

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

Non è possibile assegnare un puntatore a un array, quindi il compilatore avverte che la chiamata non va bene.

Esistono due modi per risolvere questo problema:

  • Cambia il modo in cui dichiari e assegni <=> sul lato chiamante in modo che corrisponda a ciò che la funzione prevede di ricevere:

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

    o, equivalentemente

    char* sep_foo[MAX_QTY];
    for (int i = 0; i < MAX_QTY; ++i)
      sep_foo[i] = malloc(MAX_STRING_LENGTH);
    
  • Cambia il prototipo della funzione per accettare ciò che le stai realmente dando:

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

Altri suggerimenti

Il parametro 2 dovrebbe essere

char sep_foo[][MAX_STRING_LENGTH]

Per chiarire, si sta passando un puntatore a parse () e trattandolo come un puntatore a un puntatore. Un array multidimensionale in C NON è un array di puntatori. È un singolo blocco di memoria a cui punta la variabile array. Non puoi dereferenziarlo due volte.

sep_foo è definito come un array di array. In altre parole, quando si utilizza <=>, indica l'inizio della memoria sequenziale. Ecco un modello:

(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

Tuttavia, la tua funzione prevede una matrice di puntatori (in realtà, un puntatore a un puntatore). Questo è modellato come tale:

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

Sì ... La sintassi potrebbe essere un po 'confusa per le mie spiegazioni ...

Ad ogni modo, puoi risolvere questo problema spiegando alla tua funzione come trattare il puntatore indicato. In particolare, vorresti trattarlo come un array (una sequenza di memoria):

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

Se questo è il tuo codice esatto, allora immagino che il segfault sia dovuto al fatto che non hai allocato memoria nella char* token all'interno della tua funzione di analisi, e quindi utilizzalo nella tua strcpy.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top