我正在实现具有动态调整大小的环形缓冲区。当 tail 位于 head 后面时,调整大小后,必须将缓冲区末尾的数据移至缓冲区的新末尾。为此,我编写了以下代码:
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
。这两段代码有何不同?
最佳答案
它们仅在 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]
的地址通过sizeof *b.e
字节。
如果您定义宏,您将得到最好的服务:
#define MOVE(dst, src, count) memmove((dst), (src), (count) * sizeof *(src))
并使用它代替 memmove
.
但是您当然可以更改 memmove
的最后一个参数至
(self->broadcaster.events_size-self->broadcaster.events_head)*sizeof*self->broadcaster.events
关于C memmove 相当于 for 循环 - 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52349766/