memset陷阱
最近在实现差分进化算法的时候,发现数据异常,查了好久,才知道是memset惹的祸!
#include <iostream> #include <cstring> using namespace std; void f(int s[5]) { memset(s, 0, sizeof(s)); } int main() { int s[] = {1,2,3,4,5}; f(s); for (int i = 0; i < 5; ++i) cout << s[i] << ' '; cout << endl; system("pause"); }
上面这段程序的输出竟然是:0 2 3 4 5
就是说memset只清空了第一个元素,Ohshit!
所以将数组当作参数传递的时候,不要用memset,memset应该和数组在同一块代码区。
Why?中大黑熊提示:
静态数组作为参数传入某个函数的时候,就会退化成指针,也就是该数组的首地址,其数组的长度信息就丢掉了,这就是在这个语境下退化的概念。
这也是为什么在将数组作为参数传递时,同时要将数组的长度也一并传入的原因。
当然除了再传递一个数组长度给函数这种方法来防止数组退化成指针之外,还有1种方法是使用数组的引用,加多一个'&'就可以了。
所以这个不是memset的错……memset对不起。
顺便提一提以前的小陷阱,用memset将int,bool数组置为0是可以的,但置为1是不行的;将char数组置为'1'是可以的。
Why?
memset是按字节赋值,char是字节,int是4个字节,所以char是可以的,int是不行的。(可以输出sizeof(char), sizeof(int)查看)
memset第一个参数是开始填充的地址,第二个参数是填充的byte,第三个参数要填充的字节数(注意是字节数)。
比如置为1,那么赋值的结果应该是00000001000000010000000100000001,为16843009。
通俗的讲,就是将1变为00000001,然后从数组头开始,每8位填充一个00000001,直到填充的次数等于第三个参数。最后如果是int,那就按Int的位数取出来,得到16843009。
#include <iostream> #include <cstring> using namespace std; int main() { int s[] = {1,2,3,4,5}; memset(s, 1, sizeof(s)); for (int i = 0; i < 5; ++i) cout << s[i] << ' '; cout << endl; system("pause"); }
程序的输出是:16843009 16843009 16843009 16843009 16843009
如果是置为0,那么全部都是0,所以还是0哈~
因为0全部都是0,所以可以,那么全部是f呢,答案就是-1,全部初始化为-1也是可以的。