2012-12-04 118 views
8

在更好地瞭解答案的希望 在this後給出的,可有人請向我解釋,如果 以下循環緩衝區的實現是可能的,如果不 ,何樂而不爲。取消引用空指針

#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; 
} 

據我所知,LHS必須強制轉換爲char讓我能 取消引用空指針。我也明白,這個代碼 片段:

buffer->elements[buffer->start] 

給人的元素 陣列,這也是我想非關聯化「buffer->開始」元素的地址,以獲得對 內容是地址。或者說,至少這是我從 ķ&採取R.

鑑於這一切,我怎麼告訴編譯器的 內存在該地址的內容是char,而且它是好的 取消對它的引用?有一些事情在這裏,我只是不明白 。

+0

此代碼不能編譯,不是嗎? '*(buffer-> elements [buffer-> start])'是一個'void *'的引用。 – dasblinkenlight

+0

@dasblinkenlight:這就是他的問題所在。我認爲他沒有充分理解它的作用,而是從K&R拉開了左手邊。 –

+0

Zack,是你的通用緩衝區的'類型',一旦它被初始化和分配,就被修復了嗎?如果是這樣,你可以很好地使用不同指針類型的「union」來放棄所有的指針投射。 – WhozCraig

回答

12

​​也是void *所以你需要轉換之前,你可以用它做任何事情:

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

謝謝克里斯。我沒有意識到這樣的建設是可能的。我是否正確地在讀這篇文章時告訴編譯器緩衝區 - >元素數組包含字符,然後獲取緩衝區 - >開始第n個條目的內容? – Zack

+0

@Zack:是的,這是完全正確的。 C中的數組在大多數情況下都像是指向其第一個元素的指針,因此您可以將其轉換爲不同的指針類型,並讓編譯器將它視爲不同的數組類型。 –

5

考慮到這一點,我該如何告訴編譯器該地址內存的內容是一個char,並且可以對其進行解引用?

嗯,你已經做了該行的LHS:

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

要反引用buffer->elements[n]您需要轉換這一點。

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

現在的問題是鑄造是否正確。我不能告訴你,因爲你沒有發佈​​的初始化。

+0

謝謝埃德。我想我被RHS上的所有東西搞糊塗了。關於初始化,它是在一個動態創建緩衝區的函數中完成的,它設置了一些成員的值,然後設置buffer-> elements = calloc(total,sizeof(size)); – Zack