我正在使用动态调整大小来实现环形缓冲区。当尾部位于头部之后时,必须将调整后的缓冲区末尾的数据移至新的缓冲区末尾。为此,我编写了以下代码:
memmove(self->broadcaster.events+self->broadcaster.events_head+self->broadcaster.events_size,
self->broadcaster.events+self->broadcaster.events_head,
self->broadcaster.events_size-self->broadcaster.events_head);
其中self->broadcaster.events_size
是旧大小(new_size / 2)。不幸的是,这会导致分割错误。我认为这段代码是等效的:
for (i = 0 ; i < self->broadcaster.events_size - self->broadcaster.events_head ; ++i)
self->broadcaster.events[self->broadcaster.events_size+self->broadcaster.events_head+i]=
self->broadcaster.events[self->broadcaster.events_head+i];
但是这种幼稚的for循环实现可以正常工作,所以看来我不知道如何正确使用memmove
。这两段代码有何不同?
答案 0 :(得分:1)
仅在sizeof(*self->broadcaster.events) == 1
时等效。
为清楚起见,我将self->broadcaster
替换为b
,并将events
替换为e
,并在代码中添加了一些空格。
memmove(b.e + b.e_head + b.e_size, b.e + b.e_head, b.e_size - b.e_head);
将仅复制b.e_size - b.e_head
个字节,然后循环:
for (i = 0 ; i < b.e_size - b.e_head ; ++i)
b.e[b.e_size + b.e_head + i] = b.e[b.e_head + i];
将复制(b.e_size - b.e_head) * sizeof *b.e
个字节,因为每个b.e[...] = b.e[...]
分配都在sizeof *b.e
个字节中移动,并且每个++i
都将b.e[... + i]
的地址前进{{ 1}}个字节。
如果您定义宏,将为您提供最好的服务:
sizeof *b.e
并使用它代替#define MOVE(dst, src, count) memmove((dst), (src), (count) * sizeof *(src))
。
但是您当然可以将memmove
的最后一个参数更改为
memmove