2009-10-16 16 views
6

¿Cómo debo escribir mi código, por ejemplo, en un índice de matriz específico de una matriz que sea miembro de una estructura? El siguiente código me está dando problemas.En C: ¿Cómo establecer un puntero a un miembro de la estructura que es una matriz?

// main.c 

void clean_buffers(void); // prototype 

struct DEV_STATUS { 
    unsigned char ADDR; 
    unsigned char DEV_HAS_DATA; 
    unsigned char ETH_HAS_DATA; 
    unsigned char DATA[20]; 
}; 

struct DEV_STATUS g_cmdQueue[60] = {0}; 

void main(void) { 

    clean_buffers(); 

    while (1) { 
     ;// MCU tasks   
    } 
} 

void clean_buffers(void) { 
    unsigned char theCount = 0; 
    byte queIdx; 
    for (queIdx = 0; queIdx < 59; queIdx++) { 
     struct DEV_STATUS *p_struct; 
     unsigned char *p_data; 
     p_struct = &g_cmdQueue[queIdx]; 
     p_data = &p_struct->DATA; 
     p_struct->ADDR = 0; 
     p_struct->DEV_HAS_DATA = 0; 
     p_struct->ETH_HAS_DATA = 0; 
     theCount = 0; 
     while(*(p_data+theCount) != 0) { 
      *(p_data+(theCount++)) = 0; 
     } 
    }  
} // EOF main.c 

me sale un error de compilación "miembro de struct/union espera" en la línea siguiente:

p_data = &p_struct->DATA; 

¿Cómo debo escribir un puntero si tuviera que acceder, por ejemplo, la específica valor del miembro de la estructura DATA [3]? Estoy confundido, pensé que como p_data = & p_struct-> DATA; está definido, debería ser capaz de obtenerlo usando * (pdata + 3) pero supongo que me falta algo.

+0

Gracias por todas las respuestas, lo agradezco. – Nate

+1

El mensaje de error no tiene sentido. Qué compilador estas usando? – AnT

Respuesta

8

¿Estás seguro de que estás compilando el mismo código que publicaste aquí?

Si su compilador se queja en esta línea

p_data = &p_struct->DATA; 

con un "miembro struct/union espera" mensaje, el compilador es probablemente roto.

Tenga en cuenta que &p_struct->DATA es una expresión perfectamente válida en C. No hay absolutamente ningún problema con esta expresión por sí mismo.

El problema aquí es que esto no es lo que necesita en su caso. &p_struct->DATA devuelve un puntero a toda la matriz 'DATA', es decir, un puntero de tipo unsigned char (*)[20]. Está intentando asignar este valor a un puntero de tipo unsigned char *. Esto es ilegal en C, ya que los tipos son completamente diferentes, pero tradicionalmente los compiladores C respondieron con una mera advertencia de "no coinciden" y realizaron una conversión implícita (lo que, por cierto, significa que su código original, aunque "sucio", debería todavía funciona como se esperaba).

Incluso si algún compilador decide marcar esta discrepancia como un error (lo cual está bien), aún así no debería quejarse de ningún problema del tipo "struct/union member expected". No hay tales problemas aquí.

P.S. Como ya se dijo, lo que realmente necesita es p_data = &p_struct->DATA[0], pero eso aún no explica el comportamiento extraño de su compilador. ¿Podría ser que 'DATA' es una macro definida en algún lugar antes de la definición 'clean_buffers'?

Agregado 19/10/2009: Nate, en su código tiene acceso a su matriz usando un índice theCount. Ya que está usando el acceso de índice de todos modos, realmente no hay razón para siquiera crear el puntero que está tratando de crear. El código funcionará perfectamente bien sin ningún tipo de puntero adicional, simplemente acess el campo DATA directamente

theCount = 0; 
while (p_struct->DATA[theCount] != 0) { 
    p_struct->DATA[theCount++] = 0; 

(probablemente haría uso de un ciclo for aquí).

Si realmente insiste en la creación de este puntero y sigue utilizando el acceso índice, el código debe ser algo como lo siguiente (los otros ya sugirieron que más de una vez)

p_data = p_struct->DATA; /* or &p_struct->DATA[0] */ 
... 
theCount = 0; 
while (p_data[theCount] != 0) { 
    p_data[theCount++] = 0; 

Por otra parte, se puede optar por una variante más "exótico" :)

unsigned char (*p_data)[20]; /* <- note: declared differently */ 
... 
p_data = &p_struct->DATA; /* <- note: your original version */ 
... 
theCount = 0; 
while ((*p_data)[theCount] != 0) { 
    (*p_data)[theCount++] = 0; 

Sin embargo, volviendo a una versión unsigned char *p_data, ya que cree que el puntero, podría tener más sentido utilizar una técnica de "puntero deslizante" en lugar de utilizar el acceso índice

unsigned char *p_data; 
... 
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */ 
... 
while (*p_data != 0) { 
    *p_data++ = 0; 

Como siempre, todo es una cuestión de preferencia personal. Por supuesto, nada de esto funcionará hasta que te deshagas de esa interferencia de la macro.

+0

'& p_struct-> DATA' es un puntero * a una matriz de caracteres *, no un puntero * a caracteres *. El OP quiere lo último. –

+0

@Loadmaster: Eso es exactamente lo que digo en mi publicación. ¿Lo has leído realmente? El objetivo de mi publicación es explicar el cartel original de lo que realmente significa su código original. Y para señalar que el mensaje de error es engañoso en el mejor de los casos. (En cuanto a lo que quiere el OP, eso es para que el OP decida y diga). – AnT

+0

No puedo creer que esto sea downvoted. Exactamente lo que pensaba Ahora ya no necesito agregar una respuesta :) +1 por supuesto. (Y es irónico que la respuesta aceptada sugiera el enlace incorrecto '(& p_struct) -> DATA' y esté en +4!) –

3

pierde la & en p_data = &p_struct->DATA;

p_struct ya es un puntero. Después, use p_data [] para acceder a su matriz.

+0

Gracias, por alguna razón, nunca me ha llamado a usar p_data [] para acceder a la matriz. Me preguntaba si el ampersand era superfluo, gracias por la confirmación. – Nate

+0

Su respuesta sugiere que el enlace es '(& p_struct) -> DATA', pero ese no es el caso. –

2

Lo que debe escribir es una de dos cosas:

p_data = p_struct->DATA; // DATA is the address of the first element. 

O

p_data = &p_struct->DATA[0]; // taking the address of the first element. 
1

basta con quitar el & al principio, así:

p_data = p_struct->DATA; 

que es especial sintax para matrices (recuerde que se pasan siempre como referencia) y es equivalente a:

p_data = &p_struct->DATA[0]; 

Y sí, ahora se puede utilizar * (pdata + 3)

espero que ayude.

-1

¡Uy! Gracias AndreyT

struct DEV_STATUS * p_struct; unsigned char * p_data; p_struct = & g_cmdQueue [queIdx]; p_data = & p_struct-> DATA;

p_struct es un puntero a struct DEV_STATUS.
&p_struct es la dirección de un puntero a struct DEV_STATUS (o un puntero a un puntero a struct DEV_STATUS).

es probable que desee cambiar esa línea para

p_data = p_struct->DATA; 

Oh ... su función clean_buffers() no "limpia" el elemento g_cmdQueue[59].

Y, como es un objeto global, la matriz g_cmdQueue se inicializa a todos los ceros incluso antes de que se exceda la primera instrucción de main().

+0

No, la asociatividad es incorrecta. '& p_struct-> DATA' significa' & (p_struct-> DATA) ', no para' (& p_struct) -> DATA'. No hay puntero a puntero aquí. – AnT

Cuestiones relacionadas