关于malloc申请数组空间的理解
- 【问题引入】今天在学习中发现一个现象。利用malloc申请一个数组parr。我可以用**数组+**下标的方式,也就是parr[n]的方式,去访问这块空间。我感觉很神奇。难道malloc知道自己要申请的空间是一块数组吗?为什么parr[0]可以访问?
int *parr = NULL ;
parr = (int *)malloc(20) ;
parr[0] = 4 ;
- 【思考结论】
malloc()并不知道我们申请空间干什么,他只是依照参数申请空间而已。parr[0]可以访问是因为指针的缘故。
解释
- 通过查看malloc的函数原型可以发现 malloc()的返回值是void*, 而void *我们不能使用1。 必须进行强制类型转换才可以。 可是:为什么?强制类型转换有什么用?
- 我们回顾一下数组,依int型的数组为例。数组也是通过指针来实现的。数组名就是他的指针。我们定义一个数组以及一个指向它的指针p。请观察以下代码。
int arr[3] = {1,2,3} ;
int *p = arr ;
printf("arr[1] = %d \n",arr[0] = 14) ;
printf("*(arr+1) = %d \n",*(arr+1) = 15) ;
printf("p[1] = %d \n",p[1] = 16) ;
printf("*(p+1) = %d \n",*(p+1) = 17) ;
结果如下:
3. 我们可以发现,指针是可以进行+1运算的。即:p=p+1是可行的。可p=p+1,p移动了多少?
请观察以下代码:
char a;
short b;
int c;
char *pchar = &a;
short *pshort = &b ;
int *pint = &c ;
printf("pchar = %p\t pchar+1 = %p\n",pchar,pchar+1);
printf("pshort = %p\t pshort+1 = %p\n",pshort,pshort+1);
printf("pint = %p\t pint+1 = %p\n",pint,pint+1);
return 0;
代码结果
4. 我们发现在32位系统中,pchar+1移动了一个字节、pshort+1移动了2个字节、pint+1移动了4个字节。这和他们在32位系统中的存储大小是一致的。指针p+1移动的字节数取决于自己的数据类型。数据类型占多少空间,他就移动多少字节。
5. 我们回到最开始的问题中。——malloc()知道自己开辟的空间时给数组用的吗?不!他不知道。
他只是按照参数开辟了一定字节的空间而已。但关键就在前面的强制类型转换上。
通过强制类型转换。parr指向了这块空间。那么parr+1就会移动4个字节。那么我么那就可使用
*(parr+n)来访问地址里的内容。而且 * (parr+n)可以写成parr[n]。这就解释了我一开始的问题。
6.同样它也解释了为什么malloc()要强制类型转换。因为:对于char、int等基本类型的指针+1,编译器知道要移动几个字节。而void*虽然默认也会移动一个字节2,但这不一定是我们想要的。