web-dev-qa-db-ja.com

voidポインタの間接参照

this postで与えられた答えをよりよく理解することを期待して、次の循環バッファの実装が可能かどうか、そして可能でない場合は、なぜそうでないかを誰かに説明してもらえますか?.

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

Voidポインターを逆参照できるように、LHSをcharにキャストする必要があることを理解しています。このコードフラグメントも理解しています。

buffer->elements[buffer->start]

要素配列の「buffer-> start」要素のアドレスを指定します。これも、そのアドレスのコンテンツに到達するために逆参照したいと思います。または、少なくともそれは私がK&Rから取ったものです。

それをすべて踏まえて、そのアドレスのメモリの内容がcharであり、それを逆参照しても問題ないことをコンパイラに伝えるにはどうすればよいですか?ここで何かが起こっているのですが、私にはわかりません。

11
Zack

buffer->elementsvoid *したがって、何かを行う前にキャストする必要があります。

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

それをすべて踏まえて、そのアドレスのメモリの内容がcharであり、それを逆参照しても問題ないことをコンパイラに伝えるにはどうすればよいですか?

さて、あなたはすでにその行のLHSでそれを行っています:

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

buffer->elements[n]を参照解除するには、それもキャストする必要があります。

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

ここで問題は、そのキャストが正しいかどうかです。 buffer->elementsの初期化を投稿しなかったので、それはわかりません。

5
Ed S.