Pregunta

Quiero una función simple que reciba una cadena y devuelva una matriz de cadenas después de algún análisis. Entonces, esta es mi firma de función:

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

Entonces lo llamo así:

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

...

De esta manera recibo una advertencia durante la compilación:

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

Y luego una falla de segmentación durante la ejecución en la línea marcada con / * sf aquí * /

¿Qué está mal en mi código C?

Gracias de antemano

¿Fue útil?

Solución

La advertencia es exactamente correcta. Su función quiere una matriz de punteros. Le estás dando una variedad de matrices.

Esperado:

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

Lo que proporcionó:

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

Una matriz con elementos de tipo X puede " decay " en un puntero a - X* o MAX_STRING_LENGTH. Pero el valor de sep_foo no puede cambiar en esa conversión. Solo se permite la operación de descomposición one . Necesitarías que suceda dos veces. En su caso, char** es una matriz de - *sep_foo - caracteres. La función quiere que char* sea puntero a char. Como esos no son lo mismo, el compilador te advierte. Estoy un poco sorprendido de que fuera solo una advertencia, ya que nada bueno puede venir de lo que el compilador permitió que sucediera.

En su función, podría escribir este código:

char* y = NULL;
*sep_foo = y;

Ese es el código legal ya que y es un <=>, entonces <=> es un <=>, y también lo es <=>; Puedes asignarlos. Pero con lo que intentó hacer, <=> no realmente sería un <=>; estaría apuntando a una serie de char. Su código, en efecto, estaría intentando hacer esto:

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

No puede asignar un puntero a una matriz, por lo que el compilador advierte que la llamada no es buena.

Hay dos formas de resolver esto:

  • Cambie la forma en que declara y asigna <=> en el lado llamante para que coincida con lo que la función espera recibir:

    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);
    
  • Cambie el prototipo de la función para aceptar lo que realmente le está dando:

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

Otros consejos

El parámetro 2 debería ser

char sep_foo[][MAX_STRING_LENGTH]

Para aclarar, está pasando un puntero a parse () y tratándolo como un puntero a un puntero. Una matriz multidimensional en C NO es una matriz de punteros. Es un solo bloque de memoria al que apunta la variable de matriz. No puede desreferenciarlo dos veces.

sep_foo se define como una matriz de matrices. En otras palabras, cuando usa <=>, apunta al comienzo de la memoria secuencial. Aquí hay un modelo:

(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

Sin embargo, su función espera una matriz de punteros (en realidad, un puntero a un puntero). Esto se modela como tal:

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 sintaxis puede ser un poco confusa para mis explicaciones ...

De todos modos, puede resolver este problema diciéndole a su función cómo tratar el puntero señalado. En particular, desearía tratarlo como una matriz (una secuencia de memoria):

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

Si ese es su código exacto, entonces supongo que la falla predeterminada se debe al hecho de que no ha asignado memoria a la char* token dentro de su función de análisis, y luego la usa en su strcpy.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top