1.引子
今日在看動態規划的0-1背包問題,看完后還是打算自己寫着試試,畢竟實踐才能出真知嘛.動態規划的結果是個二維數組dp,我copy書上的例子進行初始 memset(dp,0,sizeof(dp)),考慮到程序的健壯性,對於數組我都是用的動態申請,自然二維數組也不例外[動態二維數組的建立可參見本blog的延伸].
程序寫完后,但是卻不能運行,開始單步調試,當進行到dp的賦值時老是報指針的錯誤!!!開始我以為是指針越界什么的,仔細才發現dp的數組維數確實要多申請一個用來存放初始情況的值(全是0).但還是不行.只要乖乖的用兩個for循環來賦值,這下程序確實可以出結果了.這說明剛才確實是初始化的時候出了問題.這才把問題瞄准了memset(dp,0,sizeof(dp)).
printf("%d",sizoef(dp)); 我的dp是5行6列,結果是4?
2.思考
百度下memset,尤其是對整形數組進行初始化的部分.memset是以字節為單位進行初始化的.然后自己就寫了個一維數組的demo試試:
1 int b[5]; 2 int *c; 3 c = malloc(sizeof(int)*5); 4 memset(b,0,sizeof(b)); // 這個是可以成功的 5 memset(c,0,sizeof(c)); // 也可以執行 6 printf("%d",b[2]); //結果是0,b[0~3] = 0; 7 printf("%d",c[2]); //結果卻不是0!!!; 8 printf("%d %d",sizeof(b),sizeof(c));
b[2] 與 c[2]的值不一樣,兩者的初始化的差別就在sizeof(b)與sizeof(c)上,這兩個的結果是20,4!!!
memset是以字節為單位進行初始化,第4行對b的20個字節全部初始化了,第5行只對c的前4個字節初始化了,c指向的還是20個字節的內存,所以c[0] = 0;但是c[1~3]就不是了.
這兩個的不同差別在哪呢?參閱sizeof
首先這是個操作符而不是一個函數.計算數據類型的長度符的.上述中c和b都是存放5個整數,有什么不同嗎?
int b[]是一個數組,sizeof()值是其數據類型的sizeof值*其數組的長度;
int *c是一個指針變量,sizeof中說明了一個指針變量的sizeof值必定是4(32bit),與其指向的數據類型無關;
3.解決
然后在看動態規划的例子中dp是聲明的二維數組dp[][],而我是的是int **dp;是一個指向指針的指針,所以是4;
參考對一維數組初始化的例子,可以這樣:
1 // C++ -version 2 int **array; 3 array=new int *[10]; 4 for(int i=0;i<10;i++) 5 6 { 7 array[i]=new int [5]; 8 9 memset(array[i],0,5*sizeof(int)); 10 11 }
c語言的把new 換成malloc即可!
4.延伸
1. 動態的二維數組
1 int r,c; 2 int **a; //創建二維指針來指向數組 3 scanf("%d%d",&r,&c); 4 a = (int **) malloc(sizeof(int *) * r);//注意申請的指針格式 5 for (j=0;j<r;j++){ 6 a[j] = (int *) malloc(sizeof(int) * c); 7 …… 8 …… 9 }
2. memset對整形數組初始化的錯誤是初始化為1,memset對整形只能初始化為0,這個情況memset中有講;
更多閱讀課參考如下:
http://blog.csdn.net/qtyl1988/article/details/8033181
PS: 此blog是過了一夜寫的,個人也忘了當初怎么就把錯誤的原因一步步的關注到sizeof的,我記得我好想開始還不是關注的此處.反正是又學到了!