2011-01-31 5 views
4

は、私は、charにこのボイドポインタをキャストなぜなぜこのコードは* charをバッファポインタとして使用しますか?再利用する循環バッファのコードを探して

typedef struct CircularBuffer 
{ 
    void *buffer;  // data buffer 
    void *buffer_end; // end of data buffer 
    size_t capacity; // maximum number of items in the buffer 
    size_t count;  // number of items in the buffer 
    size_t sz;  // size of each item in the buffer 
    void *head;  // pointer to head 
    void *tail;  // pointer to tail 
} CircularBuffer; 

void cb_push_back(CircularBuffer *cb, const void *item) 
{ 
    if(cb->count == cb->capacity) 
     // handle error 
     memcpy(cb->head, item, cb->sz); 

    ////////////// here's the part I don't understand ////////// 
    cb->head = (char*)cb->head + cb->sz; 
    ////////////////////////////////////////////////////////// 

    if(cb->head == cb->buffer_end) 
     cb->head = cb->buffer; 
    cb->count++; 
} 

を混乱させる文字の使用に遭遇しましたか?これはある種のCイディオムですか(私はC expereienceを非常に制限しています)?おそらくポインタをインクリメントする便利な方法でしょうか?

位置ポインタのための文字の使用は、同様に、いくつかの異なるバッファコードで再起動します:

/**< Circular Buffer Types */ 
typedef unsigned char INT8U; 
typedef INT8U KeyType; 
typedef struct 
{ 
    INT8U writePointer; /**< write pointer */ 
    INT8U readPointer; /**< read pointer */ 
    INT8U size;   /**< size of circular buffer */ 
    KeyType keys[0]; /**< Element of ciruclar buffer */ 
} CircularBuffer; 

を繰り返しますが、これはポインタに関するいくつかのCプログラマが知っている便利なトリックの一種、何かのように見えます彼らが文字であれば操作が簡単です。しかし、私はただの推測だ。

+0

FYI:型は 'char *'と呼ばれ、 '* char'ではありません。 –

+0

これはtypedefの名前として構造体の名前が見えるのは初めてですが、これは奇妙なものです... – Mandrake

答えて

6

char *へのキャストは、1バイトステップでポインタを移動する場合は、ポインタ演算を正しく実行することです。これは、常にcharの定義上、1バイトのサイズがあるために機能します。 voidは単一の項目のサイズを指定していないので、代わりにvoid *ポインタを使用したポインタ演算はC標準では定義されていません。

もう1つの一般的なCイディオム(これに関連して)は、生のバイトとしていくつかのメモリにアクセスするときにunsigned char *を使用することです(unsignedタイプでは、キャストなしで各バイトの符号なしの値にアクセスできます)。メモリを文字として解釈するのではなく、生のバイトとして解釈したくないということを明確にするために、typedef ed(行に沿った何か)も使用されることがよくあります。

5

charは1バイトのサイズなので、メモリの一部の領域を単純にバイトの配列として操作する場合は、(またはsigned charまたはunsigned char)が使用されます。

+0

標準のバイトサイズ(heh)の数値型はありませんか? – morgancodes

+2

@morgancodes:はい、あります。それは 'char'と呼ばれています。 –

3

ボイドポインタは値を指すだけで、型情報はありません。したがって、voidポインタに対して加算を実行することはできません。他の型にキャストするには、ポインタ演算が必要です。ここでvoid *をchar *にキャストしてからcb-> szを追加すると、charのサイズが1であると仮定してsizeバイトだけ前に移動します。

+0

前提は必要ありません。 'sizeof(char)== 1'が保証されています。 –

1

キャストはポインタ演算を有効にします。それがなければ、cb->headはタイプであるため、式cb->head + cb->szは意味を持ちません。

ポインタがchar*にキャストされると、ポインタ添加(char*)cb->head + cb->sz「がどこcb->headポイントオブジェクトcb->sizeバイト過去のアドレスを意味します。

関連する問題