2009-10-16 12 views
6

Come dovrei scrivere il mio codice per esempio un indice di array specifico di un array che capita di essere un membro di una struttura? Il seguente codice mi sta dando problemi.In C: Come impostare un puntatore a un membro della struttura che è un array?

// 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 

ottengo un errore di compilazione "membro struct/union previsto" sulla riga seguente:

p_data = &p_struct->DATA; 

Come dovrei scrivere un puntatore se ero per accedere, ad esempio, la specifica valore del membro della struttura DATA [3]? Sono confuso, l'ho pensato come p_data = & p_struct-> DATA; è definito, dovrei essere in grado di ottenerlo usando * (pdata + 3) ma credo che mi manchi qualcosa.

+0

Grazie per tutte le risposte, lo apprezzo. – Nate

+1

Il messaggio di errore non ha senso. Che compilatore stai usando? – AnT

risposta

8

Sei sicuro che stai compilando lo stesso codice che hai postato qui?

Se il compilatore si lamenta in questa linea

p_data = &p_struct->DATA; 

con un "membro struct/union previsto" messaggio, il compilatore è probabilmente rotto.

Nota, che &p_struct->DATA è un'espressione perfettamente valida in C. Non c'è assolutamente alcun problema con questa espressione di per sé.

Il problema qui è che questo non è ciò di cui hai bisogno nel tuo caso. &p_struct->DATA restituisce un puntatore all'intero array "DATA", cioè un puntatore del tipo unsigned char (*)[20]. Stai tentando di assegnare questo valore a un puntatore di tipo unsigned char *. Questo è illegale in C, poiché i tipi sono completamente diversi, ma tradizionalmente i compilatori C hanno risposto con un semplice avviso di "mancata corrispondenza di tipo" ed eseguito una conversione implicita (che, BTW, significa che il codice originale, anche se "sporco", dovrebbe funziona ancora come previsto).

Anche se qualche compilatore decide di contrassegnare questa mancata corrispondenza come un errore (che va bene), non dovrebbe comunque lamentarsi di alcun problema di tipo "struct/union member expected". Non ci sono problemi di questo tipo qui.

P.S. Come già detto, quello di cui hai veramente bisogno è p_data = &p_struct->DATA[0], ma questo non spiega ancora lo strano comportamento del tuo compilatore. Potrebbe essere che 'DATA' sia una macro definita da qualche parte prima della definizione 'clean_buffers'?

Aggiunto 19/10/2009: Nate, nel codice si accede all'array utilizzando un indice theCount. Dato che stai comunque utilizzando l'accesso all'indice, non c'è davvero alcun motivo per creare il puntatore che stai tentando di creare. Il codice funziona perfettamente bene senza alcun ulteriore puntatore, basta acess il DATA campo direttamente

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

(probabilmente sarei utilizzare un ciclo for qui).

Se proprio insistete sulla creazione di questo puntatore e ancora utilizzando l'indice, il codice dovrebbe essere simile a quanto segue (le altre già suggerito che più di una volta)

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

Inoltre, si può optare per un altro variante "esotici" :)

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; 

Tuttavia, tornando a una versione unsigned char *p_data, dal momento che a fare una puntatore, potrebbe avere più senso utilizzare una tecnica di "puntatore scorrimento" invece di utilizzare l'accesso dell'indice

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

Come sempre, è tutta una questione di preferenze personali. Naturalmente, nulla di tutto ciò funzionerà fino a quando non ti libererai di questa interferenza dalla macro.

+0

'& p_struct-> DATA' è un puntatore * a un array di char *, non un puntatore * a un char *. L'OP vuole quest'ultimo. –

+0

@Loadmaster: è esattamente quello che sto dicendo nel mio post. Lo hai letto davvero? Il punto del mio post è quello di spiegare al poster originale che cosa significa veramente il suo codice originale. E per sottolineare che il messaggio di errore è fuorviante al meglio. (Per quanto riguarda ciò che l'OP vuole - è compito dell'OP decidere e raccontarlo). – AnT

+0

Non riesco a credere che questo sia downvoted. Esattamente quello che pensavo. Ora non ho bisogno di aggiungere una risposta :) +1 ovviamente. (Ed è ironico che la risposta accettata suggerisca l'associazione sbagliata '(& p_struct) -> DATA' ed è a +4!) –

3

perdono la & in p_data = &p_struct->DATA;

p_struct è già un puntatore. Successivamente, usa p_data [] per accedere al tuo array.

+0

Grazie, per qualsiasi motivo non mi ha mai colpito usare p_data [] per accedere all'array. Mi chiedevo se la e commerciale fosse superflua, grazie per la conferma. – Nate

+0

La tua risposta suggerisce che l'associazione è '(& p_struct) -> DATA', ma non è questo il caso. –

2

cosa si dovrebbe scrivere è una delle due cose:

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

è sufficiente rimuovere il & all'inizio, in questo modo:

p_data = p_struct->DATA; 

che è speciale sintassi per gli array (ricorda che vengono passati sempre come riferimento) ed è equivalente a:

p_data = &p_struct->DATA[0]; 

E sì, ora è possibile utilizzare * (pData + 3)

Speranza che aiuta.

-1

Oops! Grazie AndreyT

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

p_struct è un puntatore a struct DEV_STATUS.
&p_struct è l'indirizzo di un puntatore a struct DEV_STATUS (o un puntatore a un puntatore a struct DEV_STATUS).

probabilmente si desidera cambiare quella linea di

p_data = p_struct->DATA; 

Oh ... la funzione clean_buffers() non "pulito" l'elemento g_cmdQueue[59].

E, poiché si tratta di un oggetto globale, l'array g_cmdQueue viene inizializzato su tutti gli zeri anche prima dell'esecuzione della prima istruzione di main().

+0

No, si sbaglia l'associatività. '& p_struct-> DATA' sta per' & (p_struct-> DATA) ', non per' (& p_struct) -> DATA'. Non c'è puntatore a puntatore qui. – AnT

Problemi correlati