2010-04-05 12 views
6

Hola, estoy trabajando con C y tengo una pregunta sobre la asignación de punteros.c tipos incompatibles en la asignación, ¿problema con los punteros?

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 
} 

coche y tienen _car misma declaración así que ¿por qué recibo un error sobre tipos incompatibles? Supongo que tiene algo que ver con que sean punteros (porque apuntan a matrices de caracteres *, ¿no?) Pero no veo por qué eso es un problema.

cuando declare char * car; en lugar de char * car[MAXINT]; compila bien. pero no veo cómo me sería útil más adelante cuando necesito acceder a cierta información usando el índice, sería muy molesto acceder a esa información más adelante. de hecho, ni siquiera estoy seguro de si estoy yendo por el camino correcto, tal vez haya una mejor manera de almacenar un montón de cadenas en lugar de usar una matriz de caracteres *.

EDIT: yo no tenía la intención de utilizar INT_MAX (valor máximo de int), es sólo otro int, que es de unos 20.

Respuesta

3

Está creando una nueva matriz de tamaño MAXINT. Creo que quieres crear un puntero a una matriz de tamaño MAXINT.

Creación de un puntero a una matriz de char * 's:

La siguiente es una matriz de tamaño MAXINT a char * elementos:

char * car[MAXINT]; 

El siguiente es un puntero a: una matriz de tamaño MAXINT a char * elementos:

char* (*car)[MAXINT]; 

la siguiente es la forma de configurar un puntero a: una matriz de tamaño MAXINT a char * elementos:

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

Otros errores de sintaxis en la pregunta:

  • Es necesario tener un punto y coma después de su definición struct.
  • Debe utilizar foo* no foo. Por lo que debe ser:
    struct foo* thing = (struct foo *) arg;
  • debería utilizar thing no arg:
    bar = thing->_bar;
    car = thing->_car;
+0

Gracias, lo que necesitaba era un puntero a la matriz de char *. Creo que esto es lo que necesitaba (cruza el dedo) –

+0

@Fantastic Fourier: estoy de acuerdo en que necesitas un puntero a una matriz, cuyos elementos son char *. algunas otras respuestas mencionaron un puntero a una matriz char * que no es la misma. –

5

car y _car son ambas matrices, y no se puede asignar matrices en C (excepto cuando la matriz está incrustada en una estructura (o unión) y usted hace una asignación de estructura).

También son matrices de punteros a char, en lugar de punteros a matrices de char. Probablemente, lo que ha escrito en el código es lo que desea, puede almacenar punteros hasta nombres MAXINT en la matriz. Sin embargo, debe describir el tipo correctamente, como una matriz de punteros a char o char punteros.

Un puntero a una matriz de caracteres se vería así:

char (*car)[MAXINT]; 

Y un punto a una matriz de punteros a carácter (gracias, Brian) se vería así:

char *(*car)[MAXINT]; 

Tenga cuidado de MAXINT; que podría ser una matriz muy grande (en Linux, <values.h> define MAXINT como INT_MAX, que es al menos 2 -1).


El código es el siguiente:

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 
} 

Ni la asignación a la barra, ni coche, se recomienda compilar en absoluto - es una argvoid *. Presumiblemente, pretendía usar thing en alguna forma o forma.Como se ha señalado Brian, hay problemas allí, también:

O lo quieren:

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... 
} 

o si desea:

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... 
} 

O, en efecto:

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... 
} 

Finalmente, tratando con la asignación de matriz, en C puedes utilizar razonablemente memmove() para hacer esto:

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... 
} 

La función similar memcpy() no tiene la semántica fiables si las áreas a ser copiados solapamiento, mientras que memmove() hace; es más simple usar siempre memmove() porque siempre funciona correctamente. En C++, debe tener precaución al usar memmove() (o memcpy()). En este código, sería lo suficientemente seguro, pero entender por qué no es trivial.

Debe tener en cuenta que solo está copiando punteros aquí; no está copiando las cadenas que señalan los punteros. Si algo más cambia esas cadenas, afecta tanto a los valores vistos a través de car como a la variable en el código de llamada.

Un último punto - por ahora: ¿está seguro de que necesita el argumento para la función como void *? Abre el código para todo tipo de abuso que se puede evitar si se declara que la función toma un 'struct foo *' en su lugar (o incluso un 'const struct foo *').

+0

Creo que quiere una serie de punteros a char, ya que cada puntero-a-char parece representar el nombre de un auto . Sin embargo, Brian tiene un punto que es posible que pueda usar un puntero a la matriz, en lugar de copiarlo. –

+0

@Matthew: Estoy de acuerdo en que probablemente quiera lo que ha escrito en el código. Sin embargo, su descripción de lo que él tiene es errónea, que es lo que traté de decir (pero evidentemente no fue lo suficientemente claro). –

+0

Un puntero a una matriz de caracteres no es lo mismo que un puntero a una matriz de punteros de caracteres. –

2

No puede asignar una matriz de la manera en que lo hace. Puede hacer una copia de elemento-sabio.

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

Tenga en cuenta que si si las cadenas no son constantes, puede que tenga que utilizar strcpy.

+0

Si usara 'strcpy()', tendría que tener cuidado para asegurarse de que haya espacio para las cadenas en las que se va a copiar. Sin embargo, si las cadenas no son constantes, los cambios realizados en un lugar (a través de una variable) pueden aparecer inesperadamente en el otro (las cadenas apuntadas por la otra variable también cambiarían ya que ambos conjuntos de punteros apuntan al mismo espacio) –

0

notación de matriz en C es legítimamente confuso; tu código no significa lo que piensas que significa.

arg->_car significa "la dirección de la matriz _car". De forma similar, car significa "la dirección de la matriz car". Si usted está tratando de copiar el contenido de _car al coche, entonces esto va a hacerlo:

memcpy(car, _car, MAXINT); 

Pero su verdadera cuestión, creo, es "¿cuál es la mejor manera de almacenar una lista de cadenas?" Esta respuesta es: una lista dinámica (una que crece automáticamente a medida que agrega elementos).

Se podría declarar así:

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

Para añadir un coche:

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

Para una lista de los coches:

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

para quitar el coche en la posición n :

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

Esto es completamente rutinario en C. NOTA: Lo anterior está fuera de mi cabeza y no se copia de un programa en funcionamiento, por lo que no puedo prometer que todo * esté en el lugar correcto. Sospecho que es una tarea para hacer, por lo que no quiero darte todo ...

+0

es para mis redes donde la matriz se utiliza para guardar los nombres de las conexiones entrantes (el número de conexiones se maximiza en SOME_NUMBER, que es 20). Por lo tanto, creo que debería seguir con la estática, en lugar de dinámica. –

Cuestiones relacionadas