在寻找要重用的循环缓冲区代码时,我遇到了使用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++;
}
为什么将此void指针强制转换为char?这是某种C语言(我有很大的限制吗)吗?一种方便的增加指针的方法吗?
在一些不同的缓冲区代码中再次使用char作为位置指针:
/**< 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 :(得分:6)
如果要以一个字节的步长移动指针,转换为char *
是为了使指针算法正确执行;这总是有效的,因为根据定义,char
具有1个字节的大小。相反,使用void *
指针的指针算法不是由C标准定义的,因为void
没有指定单个项目的大小。
另一个常见的C语言(与此相关)是当你想以“原始字节”访问某些内存时使用unsigned char *
(unsigned
类型允许你访问每个字节的无符号值而不需要铸);它经常用typedef
ed(类似于typedef unsigned char byte;
的内容)来明确表示你不想将内存解释为字符,而是将其解释为原始字节。
答案 1 :(得分:5)
char
的大小为一个字节,因此当您想要将某些内存区域简单地作为字节数组进行操作时,会使用它(或signed char
或unsigned char
)。
答案 2 :(得分:3)
Void指针只指向一个值,并且没有类型信息。因此无法对void指针执行添加。将其转换为其他类型需要指针算法。这里将void *转换为char *然后添加cb-&gt; sz,假设char的大小为1,则按大小字节向前移动。
答案 3 :(得分:1)
强制转换启用指针算术;没有它,因为cb->head
的类型为void*
,所以表达式cb->head + cb->sz
没有意义。
指针强制转换为char*
后,指针添加(char*)cb->head + cb->sz
表示“对象cb->size
字节的地址超过cb->head
指向的位置。