跳至正文

Glibc 中的 memset

  • 技术

Glibc的效率真的快!快到让我想不到!!!
这个memset跑的贼快~!不过我还是没想通,为什么不用汇编呢?sep movw,速度可能更快!
对memset的注释如下:

C语言: [Codee#12483](http://fayaa.com/code/view/12483/)

void *memset(void *dstpp, int c, size_t len)
{
 long int dstp = (long int) dstpp;
 /* 正在翻阅为什么用long int 而不是void *. */
 /* 被高手指点了一下,不能用void *,因为它不能增,只能用char *. */

 /* 还有一位仙人告诉我, 这里用long int 纯粹只是个人喜好, 另见FreeBSD的代码:

 [http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/string/memset.c?rev=1.9](http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/string/memset.c?rev=1.9) */

 if (len >= 8) {
 size_t xlen;
 op_t cccc;
 /* 关于op_t这个类型, 在memcmp中有定义
 # define op_t unsigned long int
 # define OPSIZ (sizeof(op_t)) */

 /* 每次操作对多个字节进行赋值 */
 cccc = (unsigned char) c;
 cccc |= cccc << 8;
 cccc |= cccc << 16;
 if (OPSIZ > 4) /* 如果是64位的机子的话, 还可以再多用4个字节 */
 cccc |= (cccc << 16) << 16;

 while (dstp % OPSIZ != 0) { /* 让内存地址对齐地址总线的长度, 以
 得到最高的效率! */
 ((byte *) dstp)[0] = c;
 dstp += 1;
 len -= 1;
 }

 xlen = len / (OPSIZ * 8); /* 每次赋值8个,也就是说如果在32位的机子上的话
 每次赋值4*8=32个字节,64位的机子就是64字节 */
 while (xlen > 0) {
 ((op_t *) dstp)[0] = cccc;
 ((op_t *) dstp)[1] = cccc;
 ((op_t *) dstp)[2] = cccc;
 ((op_t *) dstp)[3] = cccc;
 ((op_t *) dstp)[4] = cccc;
 ((op_t *) dstp)[5] = cccc;
 ((op_t *) dstp)[6] = cccc;
 ((op_t *) dstp)[7] = cccc;
 dstp += 8 * OPSIZ;
 xlen -= 1;
 }
 len %= OPSIZ * 8; /* 得到余下的未赋值的字节数,一定小于32 */

 xlen = len / OPSIZ; /* 每次赋值1个, 32位机子4个字节一次, 64位8个 */
 while (xlen > 0) {
 ((op_t *) dstp)[0] = cccc;
 dstp += OPSIZ;
 xlen -= 1;
 }
 len %= OPSIZ; /* 得到余下的未赋值的字节书,一定小于4 */
 }

 while (len > 0) { /* 最后剩下的几个字节单独赋值 */
 ((byte *) dstp)[0] = c;
 dstp += 1;
 len -= 1;
 }

 return dstpp;
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注