如何memset()内存到某个模式而不是单个字节?

bod*_*ydo 15 c memory design-patterns memset

我今天面临一个问题,我需要将内存更改为某种模式,如0x 11223344,以便整个内存看起来像(十六进制):

1122334411223344112233441122334411223344112233441122334411223344...
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚如何使用memset(),因为它只需要一个字节,而不是4个字节.

有任何想法吗?

谢谢,Boda Cydo.

Ste*_*non 9

在OS X上,一个memset_pattern4( )用于此; 我希望其他平台有类似的API.

我不知道一个简单的可移植解决方案,除了用循环填充缓冲区(这非常简单).

  • 我忘了我可以使用循环.谢谢你的提醒.现在尝试使用循环. (2认同)

Aar*_*lla 6

递归复制内存,使用您已经填充的区域作为每次迭代的模板(O(log(N)):

int fillLen = ...;
int blockSize = 4; // Size of your pattern

memmove(dest, srcPattern, blockSize);
char * start = dest;
char * current = dest + blockSize;
char * end = start + fillLen;
while(current + blockSize < end) {
    memmove(current, start, blockSize);
    current += blockSize;
    blockSize *= 2;
}
// fill the rest
memmove(current, start, (int)end-current);
Run Code Online (Sandbox Code Playgroud)

[编辑]我对"O(log(N))"的意思是运行时将比手动填充内存快得多,因为memmove()通常使用特殊的,手动优化的快速组装循环.

  • 这是对"memmove"的O(log(n))调用; 实际的复杂性仍然是O(n). (7认同)

jkr*_*mer 6

一种有效的方法是将指针转换为所需大小的指针(以字节为单位)(例如,uint32_t为4个字节)并填充整数.虽然这有点难看.

char buf[256] = { 0, };
uint32_t * p = (uint32_t *) buf, i;

for (i = 0; i < sizeof(buf) / sizeof(* p); i++) {
    p[i] = 0x11223344;
}
Run Code Online (Sandbox Code Playgroud)

没测试过!

  • 需要注意的一点是`buf`可能无法满足平台上`uint32_t`的对齐要求.如果`buf`是`malloc`的结果,你不需要担心这个,但是如果它(比如说)通过你无法控制的代码作为参数传入,你需要检查对齐在以这种方式写入之前,否则这将导致某些平台上的无效访问. (6认同)
  • 据我所知,代码在一般情况下包含 UB(不仅仅是这个片段 - 除了前面提到的对齐之外) - “buf”可以作为其他内容访问,然后“char”或“uint32_t”违反严格的指针别名规则 -因此,如果 OP 想要填充“float”数组,他就会遇到 UB。 (3认同)
  • 这不是很有效; 在我的例子中使用`memmove()`要快得多,因为它使用特殊的汇编操作和手动优化的代码. (2认同)
  • @Aaron Digulla:这个主张取决于很多东西:例如,对于小缓冲区,你将被函数调用开销宰杀,重复对`memmove()`的小调用.对于"典型"缓冲区,您的解决方案在大多数平台上可能会更快,并且具有良好优化的库,但对于真正庞大的缓冲区,您的解决方案将渐近地占用两倍的页面错误,并且在大多数平台上速度将近两倍. (2认同)

Lau*_*eau 5

如果您的模式适合wchar_t,则可以wmemset()像使用memset().