C语言中的sizeof中的数组和指针
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的,我记得我好想开始还不是关注的此处.反正是又学到了!