Question

Je veux une fonction simple qui reçoit une chaîne et retourne un tableau de chaînes après une analyse. Donc, voici ma signature de fonction:

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

Ensuite, je l'appelle comme suit:

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

...

Ainsi, je reçois un avertissement lors de la compilation:

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

Et puis une erreur de segmentation lors de l'exécution dans la ligne marquée avec / * sf ici * /

Qu'est-ce qui ne va pas dans mon code C?

Merci d'avance

Était-ce utile?

La solution

L’avertissement est tout à fait correct. Votre fonction veut un tableau de pointeurs. Vous lui donnez un tableau de tableaux.

Attendu:

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

Ce que vous avez fourni:

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

Un tableau avec des éléments de type X can " decay " dans un pointeur sur - X* ou MAX_STRING_LENGTH. Mais la valeur de sep_foo n'est pas autorisée à changer dans cette conversion. Seule une opération de désintégration est autorisée. Vous auriez besoin que cela se produise deux fois. Dans votre cas, char** est un tableau de-<-> caractères. La fonction veut que *sep_foo soit un pointeur sur un caractère. Puisque ce ne sont pas les mêmes, le compilateur vous avertit. Je suis un peu surpris que ce ne soit qu'un avertissement, car rien de ce que le compilateur a permis de faire ne peut être bénéfique.

Dans votre fonction, vous pouvez écrire ce code:

char* y = NULL;
*sep_foo = y;

Ce code est légal car char* est un y, donc <=> est un <=>, il en est de même <=>; vous pouvez les assigner. Mais avec ce que vous avez essayé de faire, <=> ne serait pas vraiment être un <=>; il s'agirait d'un tableau de caractères. En réalité, votre code essaierait de le faire:

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

Vous ne pouvez pas affecter de pointeur à un tableau. Le compilateur vous avertit que l'appel n'est pas bon.

Il existe deux manières de résoudre ce problème:

  • Modifiez la façon dont vous déclarez et allouez <=> du côté appelant afin qu'il corresponde à ce que la fonction s'attend à recevoir:

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

    ou, de manière équivalente

    char* sep_foo[MAX_QTY];
    for (int i = 0; i < MAX_QTY; ++i)
      sep_foo[i] = malloc(MAX_STRING_LENGTH);
    
  • Modifiez le prototype de la fonction pour accepter ce que vous lui donnez réellement:

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

Autres conseils

Le paramètre 2 devrait être

char sep_foo[][MAX_STRING_LENGTH]

Pour clarifier, vous passez un pointeur sur parse () et le traitez comme un pointeur sur un pointeur. Un tableau multidimensionnel en C n'est PAS un tableau de pointeurs. C'est un bloc de mémoire unique pointé par la variable tableau. Vous ne pouvez pas le déréférencer deux fois.

sep_foo est défini comme un tableau de tableaux. En d'autres termes, lorsque vous utilisez <=>, il pointe vers le début de la mémoire séquentielle. Voici un modèle:

(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

Cependant, votre fonction attend un tableau de pointeurs (en fait, un pointeur sur un pointeur). Ceci est modélisé comme tel:

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

Ouais ... La syntaxe peut être un peu déroutant pour mes explications ...

Quoi qu’il en soit, vous pouvez résoudre ce problème en indiquant à votre fonction comment traiter le pointeur pointé. En particulier, vous voudriez le traiter comme un tableau (une séquence de mémoire):

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

S'il s'agit de votre code exact, alors je suppose que l'erreur de segmentation résulte du fait que vous n'avez pas alloué de mémoire à la char* token fonction de votre fonction d'analyse, puis que vous l'utilisez dans votre stratégie.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top