解引用空指针

11

希望能更好地理解这篇文章中提供的答案,有人可以请解释一下下面的环形缓冲区实现是否可行,如果不行的话,请说明原因。

#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类型,这样才能对void指针进行解引用。我也理解这段代码片段:

buffer->elements[buffer->start]

给出了元素数组中'buffer->start'元素的地址,我也想通过解引用获得该地址的内容。至少这是我从K&R中理解的。

鉴于此,我该如何告诉编译器该地址内存的内容是char类型,并且可以解引用它呢?这里有些东西我还不太理解。


这段代码无法编译,是吗?*(buffer->elements[buffer->start]) 是对 void* 的解引用。 - Sergey Kalinichenko
@dasblinkenlight:他的问题就是关于这个的。我认为他从K&R中提取了左侧,但并没有完全理解它的作用。 - Ed S.
Zack,一旦你的通用缓冲区被初始化和分配,它的“类型”是否固定?如果是这样,你可以使用不同指针类型的“联合体”来避免所有指针转换。 - WhozCraig
这是个好主意 - 我以前从未使用过 union,而且已经忘记了它们。我最好去读一些资料 - 感谢您的建议! - Zack
2个回答

14

buffer->elements 也是一个 void *,所以在对其进行任何操作之前,您需要进行类型转换:

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

谢谢Chris。我没有意识到这样的构造是可能的。我的理解是,这告诉编译器buffer->elements数组包含字符,并获取缓冲区->start第n个条目的内容,我的理解正确吗? - Zack
@Zack:是的,完全正确。在C语言中,数组在大多数情况下实际上被视为指向其第一个元素的指针,因此您可以将其强制转换为不同的指针类型,并让编译器将其视为不同的数组类型。 - Chris Dodd

5
鉴于这一点,我该如何告诉编译器该地址内存的内容是char类型,并且可以安全地对其进行解引用操作?
好的,在该行代码的左边你已经完成了这个步骤:
*(char*)element = *(buffer->elements[buffer->start]);

要取消引用 buffer->elements[n],您还需要对其进行转换。
*(char*)element = *((char*)buffer->elements)[buffer->start];

现在的问题是这个转换是否正确。我无法告诉你,因为你没有发布buffer->elements的初始化。

谢谢Ed。我想我被右手边的所有东西搞糊涂了。关于初始化,它是在一个函数中完成的,该函数动态创建缓冲区,设置一些成员的值,然后buffer->elements = calloc(total, sizeof(size))。 - Zack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接