我今天面临一个问题,我需要将内存更改为某个模式,如0x 11223344
,以便整个内存看起来像(十六进制):
1122334411223344112233441122334411223344112233441122334411223344...
我无法弄清楚如何使用memset(),因为它只需要一个字节,而不是4个字节。
有什么想法吗?
谢谢,Boda Cydo。
答案 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位存储),但是即使不进行优化,它也应与库内存集一样快,因为这样的简单循环受内存访问的限制