最近在實現差分進化算法的時候,發現數據異常,查了好久,才知道是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也是可以的。