21

我需要将重复模式写入内存(例如0x11223344),以便整个内存看起来像(以十六进制表示):

1122334411223344112233441122334411223344112233441122334411223344...

我不知道该怎么做,memset()因为它只需要一个字节,而不是 4 个字节。

有任何想法吗?

4

7 回答 7

9

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

我不知道一个简单的便携式解决方案,除了用循环填充缓冲区(这非常简单)。

于 2010-07-27T15:16:32.430 回答
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()通常使用特殊的、手动优化的汇编程序循环,速度非常快。

于 2010-07-27T15:28:30.423 回答
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;
}

未测试!

于 2010-07-27T16:24:39.297 回答
5

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

于 2010-07-27T16:09:52.720 回答
3

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

于 2010-07-27T15:14:57.727 回答
2

好吧,这样做的正常方法是手动设置前四个字节,然后memcpy(ptr+4, ptr, len -4)

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

请注意,这“通常”有效,但不能保证,具体取决于您的 CPU 架构和您的 C 运行时库。

于 2010-07-27T15:17:01.743 回答
1

标准 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 位存储),但即使没有优化,它也应该与库 memset 一样快,因为这种简单的循环是内存访问受限的。

于 2019-08-31T19:03:11.137 回答