2012-12-04 13 views
8

W nadziei na lepsze zrozumienie z odpowiedziami podane w this postu, może ktoś mi wyjaśnić, czy po wdrożenie bufor kołowy jest to możliwe, a jeśli nie, to dlaczego.dereferencing void wskaźniki

#define CB_TYPE_CHAR  0 
#define CB_TYPE_FLOAT 1 

... 

typedef struct CBUFF 
{ 
    uint16 total;  /* Total number of array elements */ 
    uint16 size;  /* Size of each array element */ 
    uint16 type;  /* Array element type */ 
    uint16 used;  /* Number of array elements in use */ 
    uint16 start;  /* Array index of first unread element */ 
    void *elements;  /* Pointer to array of elements */ 
} CBUFF; 

... 

void cbRead(CBUFF *buffer, void *element) 
{ 
    if (buffer->type == CB_TYPE_CHAR) 
    { 
    /* The RHS of this statement is the problem */ 
     *(char*)element = *(buffer->elements[buffer->start]); 
    } 

    /* Other cases will go here */ 

    buffer->start = (buffer->start + 1) % buffer->total; 

    --buffer->used; 
} 

Rozumiem, że LHS muszą być oddane do char tak, że mogę nieprawidłowego wskaźnika void. Rozumiem też, że ten kod fragment:

buffer->elements[buffer->start] 

daje adres „buffer-> Start” elementu elementów tablicy, które również chcą dereference aby dostać się do zawartości tego adres. Albo przynajmniej to, co biorę od K & R.

Biorąc pod uwagę wszystko to, w jaki sposób mogę poinformować kompilator, że treść pamięci pod tym adresem jest char, i że jest w porządku, aby dereference nim ? Coś tu się dzieje, po prostu nie rozumiem.

+0

Ten kod nie kompiluje, prawda? '* (Buffer-> elements [buffer-> start])' jest dereferencją 'void *'. – dasblinkenlight

+0

@dasblinkenlight: O to chodzi w jego pytaniu. Myślę, że wyciągnął lewą stronę z K & R, nie rozumiejąc w pełni, co robi. –

+0

Zack, czy "typ" ogólnego bufora jest ustalany po jego inicjalizacji i przydzieleniu? Jeśli tak, możesz być dobrze obsłużony przy użyciu "unii" różnych typów wskaźników, aby zrezygnować z rzucania całego wskaźnika. – WhozCraig

Odpowiedz

12

buffer->elements również void * więc trzeba go rzucić, zanim będzie można nic zrobić z nim:

*(char*)element = ((char *)buffer->elements)[buffer->start]; 
+0

Dzięki Chris. Nie zdawałem sobie sprawy, że taka konstrukcja jest możliwa. Czy mam rację czytając to jako informując kompilator, że tablica buforów-> elementów zawiera znaki i aby następnie uzyskać zawartość bufora-> start nth entry? – Zack

+0

@Zack: tak, to jest dokładnie poprawne. Tablice w C są naprawdę traktowane jak wskaźniki do ich pierwszego elementu na wiele sposobów, więc możesz rzucić go do innego typu wskaźnika i uzyskać kompilator traktować go tak, jakby był inny typ tablicy. –

5

Biorąc pod uwagę to wszystko, w jaki sposób mogę poinformować kompilator, że zawartość pamięci pod tym adresem jest char, i że jest w porządku, aby dereference nim?

Cóż, już to zrobić na tej linii LHS:

*(char*)element = *(buffer->elements[buffer->start]); 

Aby derefence buffer->elements[n] trzeba będzie oddać, że dobrze.

*(char*)element = *((char*)buffer->elements)[buffer->start]; 

Teraz pytanie brzmi, czy ten rzut jest poprawny. Nie mogę ci tego powiedzieć, ponieważ nie opublikowałeś inicjalizacji buffer->elements.

+0

Dzięki Ed. Chyba byłem zdezorientowany wszystkimi rzeczami na RHS. Jeśli chodzi o inicjalizację, odbywa się to w funkcji, która dynamicznie tworzy bufor, ustawia wartość kilku elementów, a następnie bufor-> elementy = calloc (total, sizeof (size)); – Zack