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

时间:2010-07-27 15:10:28

标签: c memory design-patterns memset

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

1122334411223344112233441122334411223344112233441122334411223344...

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

有什么想法吗?

谢谢,Boda Cydo。

8 个答案:

答案 0 :(得分:9)

在OS X上,为此使用memset_pattern4( );我希望其他平台也有类似的API。

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

答案 1 :(得分: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);

[编辑]我对“O(log(N))”的意思是运行时将比手动填充内存快得多,因为memmove()通常使用特殊的,手动优化的汇编程序循环非常快。

答案 2 :(得分:5)

一种有效的方法是将指针转换为所需大小的指针(以字节为单位)(例如,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;
}

未经测试!

答案 3 :(得分:4)

您可以在某处设置序列,然后使用memcpy()将其复制到您需要的位置。

答案 4 :(得分:4)

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

答案 5 :(得分:2)

那么,正常的方法是手动设置前四个字节,然后memcpy(ptr+4, ptr, len -4)

将前四个字节复制到后四个字节,然后将后四个字节复制到第三个字节,依此类推。

请注意,这个“通常”有效,但根据您的CPU架构和您的C运行时库,无法保证。

答案 6 :(得分:0)

使用&#34; memcpy&#34;或&#34; memset&#34;也许不是有效的方法。

不要放弃使用&#34;等#34;或&#34;而&#34;,当lib定义的函数执行相同的操作时。

答案 7 :(得分:0)

标准C库没有此类功能。但是memset通常实现为展开循环,以最大程度地减少分支和条件检查:

static INLINE void memset4(uint32_t *RESTRICT p, uint32_t val, int len) {
  uint32_t *end = p + (len&~0x1f); //round down to nearest multiple of 32
  while (p != end) { //copy 32 times
    p[ 0] = val;
    p[ 1] = val;
    p[ 2] = val;
    p[ 3] = val;
    p[ 4] = val;
    p[ 5] = val;
    p[ 6] = val;
    p[ 7] = val;
    p[ 8] = val;
    p[ 9] = val;
    p[10] = val;
    p[11] = val;
    p[12] = val;
    p[13] = val;
    p[14] = val;
    p[15] = val;
    p[16] = val;
    p[17] = val;
    p[18] = val;
    p[19] = val;
    p[20] = val;
    p[21] = val;
    p[22] = val;
    p[23] = val;
    p[24] = val;
    p[25] = val;
    p[26] = val;
    p[27] = val;
    p[28] = val;
    p[29] = val;
    p[30] = val;
    p[31] = val;
    p += 32;
  }
  end += len&0x1f; //remained
  while (p != end) *p++ = val; //copy remaining bytes
}

好的编译器可能会使用一些特定于CPU的指令对其进行进一步优化(例如,使用SSE 128位存储),但是即使不进行优化,它也应与库内存集一样快,因为这样的简单循环受内存访问的限制