C memmove相当于for loop - segfault

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C memmove相当于for loop - segfault相关的知识,希望对你有一定的参考价值。

我正在使用动态调整大小来实现环形缓冲区。当尾部在头部后面时,缓冲区末尾的数据必须在调整大小后移动到缓冲区的新端。为了做到这一点,我做了以下代码:

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->broadcasterbevents替换了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 loop - segfault的主要内容,如果未能解决你的问题,请参考以下文章

memmove 是不是移动元素(与 for 循环相同),还是一次抓取整个内存块?

Swift中的Loop for Loop总和

031005 for 循环

Sqlite3.c 中的 For-loop 语法错误

C/C++ memmove与memcpy的区别及实现

开心模拟—— 用C模拟实现memcpy和memmove函数