简述
在处理数组的时候经常需要频繁地将数组初始化为0,这时候有两种选择,一种是使用for循环,一个元素一个元素地赋值;再者就是使用包含于string.h
头文件的memset
函数了。
原文:http://blog.csdn.net/hackbuteer1/article/details/7343189
函数原型
1 | void* memset(void* s, int c, size_t n) |
作用:将s所指向的某一块内存中的每个字节的内容全部设置为c指定的ASCII值, 块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作。
函数使用
memset
函数通常都被当做当作万能的初始化工具,例如:1
2
3const int n = 10000;
int arr[n];
memset(arr, 1, n * sizeof(int));
这样得到的arr数组一定不是全0,而是16843009,下面解释原因。
首先,变量类型的本质只是标志从某一内存地址开始读取的位数,强制转换就是改变读取位数的大小。
c的二进制表示: 00000000 00000000 00000000 00000001 (32位)
- c转换为
unsigned char
后:00000001(8位) - 将指针p(
unsigned char
类型)的每一元素(8位)赋值为00000001,循环4n
次。 memset
结束后,arr
的每个元素按照int
类型读取,读出来的就是00000001 00000001 00000001 00000001,十进制就是16843009。
不过如果是memset(arr, 0, n * sizeof(int))
的话可以使用,因为32位都是0。memset(arr, -1, n * sizeof(int))
也可以将arr
数组成功赋值为-1,因为计算机在存储负数的时候采用的是补码表示,-1的补码为:11111111 11111111 11111111 11111111,因此可以成功地赋值。
效率测试
再来说memset
的效率问题。使用memset
函数与将上面的函数代码写在自己的程序里是不一样的,C标准库中的memset
对Cache
的利用做了优化,具体的在《C专家编程》151页有解释,这里给出测试代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
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))
的情况,效率比手动赋值要高的多,但大量的初始化也需要谨慎使用。