我建议使用memmove 进行复制。它具有与memcpy 相同的签名和功能,除了在重叠区域之间复制是安全的(这就是您所描述的)。
对于零填充,memset 通常就足够了。例如,在不使用底层零序列表示空指针的情况下,您需要根据类型自行使用赋值。
出于这个原因,您可能希望将memmove 和memset 操作隐藏在抽象之后,例如:
#include <string.h>
void copy_int(int *destination, int *source, size_t size) {
memmove(destination, source, size * sizeof *source);
}
void zero_int(int *seq, size_t size) {
memset(seq, 0, size * sizeof *seq);
}
int main(void) {
int array[] = { 0, 1, 2, 3, 4, 5 };
size_t index = 2
, size = sizeof array / sizeof *array - index;
copy_int(array, array + index, size);
zero_int(array + size, index);
}
如果 memmove 或 memset 将来变得不适合用例,则可以很容易地放入您自己的复制/零循环。
至于您奇怪的分析器结果,我想您可能正在使用一些过时(或严重降频)的实现,或者试图复制巨大的数组......否则,28 毫秒确实看起来很荒谬。尽管如此,您的分析器肯定会发现 memmove 和 memset 在执行实际 I/O 工作的程序中并不是一个重大瓶颈,对吧? I/O 肯定是瓶颈吧?
如果memmove+memset 确实是一个瓶颈,您可以尝试实现一个循环数组来避免复制。例如,下面的代码试图在input_file这个比喻性的大海捞针中找到needle...
否则,如果 I/O 是一个瓶颈,可以应用一些调整来减少它。例如,以下代码使用setvbuf 暗示底层实现尝试使用底层缓冲区来读取文件块,尽管代码使用fgetc 一次读取一个字符。
void find_match(FILE *input_file, char const *needle, size_t needle_size) {
char input_array[needle_size];
size_t sz = fread(input_array, 1, needle_size, input_file);
if (sz != needle_size) {
// No matches possible
return;
}
setvbuf(input_file, NULL, _IOFBF, BUFSIZ);
unsigned long long pos = 0;
for (;;) {
size_t cursor = pos % needle_size;
int tail_compare = memcmp(input_array, needle + needle_size - cursor, cursor),
head_compare = memcmp(input_array + cursor, needle, needle_size - cursor);
if (head_compare == 0 && tail_compare == 0) {
printf("Match found at offset %llu\n", pos);
}
int c = fgetc(input_file);
if (c == EOF) {
break;
}
input_array[cursor] = c;
pos++;
}
}
注意这里怎么不需要memmove(或归零,FWIW)?我们简单地操作,就好像数组的开始在cursor,结束在cursor - 1,我们通过模needle_size 包装以确保没有上溢/下溢。然后,在每次插入之后,我们只需增加 cursor...