下面来看memset的实现:(代码来自《C标准库》P398)
[cpp] view plain copy void *(memset) (void *s,int c,size_t n) { const unsigned char uc = c; unsigned char *su; for(su = s;0 < n;++su,--n) *su = uc; return s; } 第3行把int类型的c转换成unsigned char类型,意味着截去c的高24位,只保留低8位。第4行把s当作unsigned char*类型,也就是说su中的每一个元素按8位计算。 现在来看看文章开头的那个代码会做什么。 c的二进制 : 00000000000000000000000000000001(32位) 1、c转换为unsigned char 后:00000001(8位) 2、将指针su(unsigned char类型)的每一元素(8位)赋值为00000001,循环4n次。 3、memset()结束后,arr的每个元素按照int类型读取,读出来的就是1000000010000000100000001,十进制就是16843009。 不过如果是memset(arr,0,n*sizeof(int));的话可以使用,因为32位都是0 再来说memset()的效率问题。使用memset函数与将上面的函数代码写在自己的程序里是不一样的,C标准库中的memset对Cache的利用做了优化,具体的在《C专家编程》151页有解释(其实是我没看懂),这里给出测试:
[cpp] view plain copy #include <string.h> #define MAXSIZE 100000 int main() { char arr[MAXSIZE]; for(int i=0;i<10000;i++) { memset(arr,'0',sizeof(arr)); // for(int j=0;j<MAXSIZE;j++) // arr[0] = '0'; } return 0; } 程序里的注释部分与memset行分别使用,结果是使用memset的程序运行时间大约为0.1s,而用for循环的程序要3s多。
综上:memset()可以用在字符数组的初始化以及类似于memset(arr,0,n*sizeof(int));的情况,效率比手动赋值要高的多。
故可以用memset给一个数组初始化为0或者-1