2009-10-16 14 views
6

Jak napisać mój kod do przykładu konkretny indeks tablicy tablicy, która jest członkiem struktury? Poniższy kod daje mi problemy.In C: Jak ustawić wskaźnik do elementu struktury, który jest tablicą?

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

otrzymuję błąd kompilatora „członek struct/union oczekiwany” na następującej linii:

p_data = &p_struct->DATA; 

Jak mam napisać wskaźnik gdybym miał dostęp, na przykład, specyficzne wartość danych członka struktury [3]? Jestem zdezorientowany, myślałem, że jako p_data = & p_struct-> DATA; jest zdefiniowany, powinienem być w stanie go uzyskać za pomocą * (pdata + 3), ale myślę, że czegoś brakuje.

+0

Dzięki za wszystkie odpowiedzi, doceniam to. – Nate

+1

Komunikat o błędzie nie ma sensu. Z jakiego kompilatora korzystasz? – AnT

Odpowiedz

8

Czy jesteś pewien, że kompilujesz ten sam kod, który tutaj zamieściłeś?

Jeśli kompilator narzeka na tej linii

p_data = &p_struct->DATA; 

z „członka struct/union oczekiwanego” wiadomość, kompilator jest prawdopodobnie uszkodzony.

Pamiętaj, że &p_struct->DATA jest poprawnym wyrażeniem w C. Nie ma absolutnie żadnych problemów z tym wyrażeniem.

Problem polega na tym, że nie jest to potrzebne w twoim przypadku. &p_struct->DATA zwraca wskaźnik do całej tablicy "DATA", tj. Wskaźnik typu unsigned char (*)[20]. Próbujesz przypisać tę wartość do wskaźnika typu unsigned char *. Jest to nielegalne w C, ponieważ typy są zupełnie inne, ale tradycyjnie kompilatory C odpowiedziały na to ostrzeżeniem "niedopasowanie typu" i wykonywały niejawną konwersję (która, BTW, oznacza, że ​​twój oryginalny kod, choćby "brudny", powinien nadal działają zgodnie z przeznaczeniem).

Nawet jeśli jakiś kompilator zdecyduje się oznaczyć to niedopasowanie jako błąd (co jest w porządku), nadal nie powinien narzekać na żadne problemy typu "oczekiwany członek struct/union". Tutaj nie ma takich problemów.

P.S. Jak już powiedzieliśmy, to, czego naprawdę potrzebujesz, to p_data = &p_struct->DATA[0], ale to nadal nie wyjaśnia dziwnego zachowania twojego kompilatora. Czy to możliwe, że "DATA" to makro zdefiniowane gdzieś przed definicją "clean_buffers"?

Dodano 10/19/2009: Nate, w swoim kodzie uzyskujesz dostęp do swojej tablicy przy użyciu indeksu theCount. Ponieważ i tak korzystasz z dostępu do indeksu, naprawdę nie ma powodu, aby nawet tworzyć wskaźnik, który próbujesz utworzyć. Kod działa perfekcyjnie bez dodatkowego wskaźnika, podobnie acess pole DATA bezpośrednio

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

(pewnie bym użyć for cykl tutaj).

Jeśli naprawdę nalegać na stworzenie tego wskaźnika, a także nadal korzystać z dostępu do indeksu, kod powinien wyglądać tak jak poniżej (inni już zasugerował, że więcej niż jeden raz)

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

Ponadto, można zdecydować się na bardziej „egzotyczne” wariant :)

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; 

jednak, wracając do wersji unsigned char *p_data, ponieważ tworzenie tego wskaźnika, może to więcej sensu używać techniki „pointer przesuwne” zamiast używać dostępu indeksu

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

To wszystko zależy od osobistych preferencji. Oczywiście nic z tego nie zadziała, dopóki nie pozbędziesz się tej interferencji z makra.

+0

'& p_struct-> DATA' to * wskaźnik do tablicy char *, a nie * wskaźnik do znaku *. PO chce tego drugiego. –

+0

@ Ladadmaster: Dokładnie to, co mówię w moim poście. Czy naprawdę to przeczytałeś? Celem mojego postu jest wyjaśnienie oryginalnego plakatu, jaki naprawdę ma jego oryginalny kod. I wskazać, że komunikat o błędzie jest w najlepszym przypadku mylący. (Jeśli chodzi o to, co chce OP - to jest dla OP do podjęcia decyzji i do opowiedzenia.) – AnT

+0

Nie mogę uwierzyć, że jest to odrzucone. Dokładnie to, co myślałem. Teraz nie muszę już dodawać odpowiedzi :) +1 oczywiście. (A ironią jest, że przyjęta odpowiedź sugeruje niewłaściwe wiązanie '(& p_struct) -> DATA' i jest na +4!) –

3

Lose & w p_data = &p_struct->DATA;

p_struct jest już wskaźnikiem. Następnie użyj p_data [], aby uzyskać dostęp do twojej tablicy.

+0

Dziękuję, bez względu na to, z jakiego powodu nigdy nie skorzystałem z p_data [], aby uzyskać dostęp do tablicy. Zastanawiałem się, czy ampersand jest zbyteczny, dzięki za potwierdzenie. – Nate

+0

Twoja odpowiedź sugeruje, że powiązanie to '(& p_struct) -> DATA', ale tak nie jest. –

2

Co należy napisać to jedna z dwóch rzeczy:

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

LUB

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

Wystarczy usunąć & na początku, jak to:

p_data = p_struct->DATA; 

To specjalny sintax dla tablic (pamiętaj, że są one zawsze przekazywane jako referencje) i jest to odpowiednik:

p_data = &p_struct->DATA[0]; 

I tak, teraz możesz używać * (pData + 3)

Nadzieję, że to pomaga.

-1

Ups! Dziękujemy AndreyT

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

p_struct to wskaźnik do struct DEV_STATUS.
&p_struct to adres wskaźnika do struct DEV_STATUS (lub wskaźnik do wskaźnika do struct DEV_STATUS).

Prawdopodobnie chcesz zmienić tę linię do

p_data = p_struct->DATA; 

Oh ... czynność clean_buffers() nie "czyste" element g_cmdQueue[59].

A ponieważ jest to obiekt globalny, tablica g_cmdQueue jest inicjalizowana na wszystkie zera, nawet przed pierwszą instrukcją wydań main().

+0

Nie, idziesz na asocjatywę źle. '& p_struct-> DATA' oznacza' & (p_struct-> DATA) ', a nie' (& p_struct) -> DATA'. Tutaj nie ma wskaźnika do wskaźnika. – AnT