关于malloc申请数组空间的理解

本文探讨了C语言中使用malloc动态分配内存时如何通过指针访问数组元素。malloc函数并不知道分配的内存将用于数组,但它返回的void*指针可以通过类型转换成为数组指针。通过指针加法操作,可以访问分配的连续内存空间,这是因为指针移动的字节数与其指向的数据类型大小有关。强制类型转换确保了正确的字节移动,使得可以使用parr[n]的形式访问元素。文章还强调了void*指针加一可能不总是移动正确字节数,因此通常需要类型转换来确保安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于malloc申请数组空间的理解

  • 【问题引入】今天在学习中发现一个现象。利用malloc申请一个数组parr。我可以用**数组+**下标的方式,也就是parr[n]的方式,去访问这块空间。我感觉很神奇。难道malloc知道自己要申请的空间是一块数组吗?为什么parr[0]可以访问?
int *parr = NULL ;
parr = (int *)malloc(20) ;
parr[0] = 4 ;
  • 【思考结论】
    malloc()并不知道我们申请空间干什么,他只是依照参数申请空间而已。parr[0]可以访问是因为指针的缘故。

解释

  1. 通过查看malloc的函数原型可以发现 malloc()的返回值是void*, 而void *我们不能使用1。 必须进行强制类型转换才可以。 可是:为什么?强制类型转换有什么用?
    malloc函数man手册
  2. 我们回顾一下数组,依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,但这不一定是我们想要的。


  1. void*当然是可以使用的,但在实际编程不要使用。 ↩︎

  2. 我在我的编译器中尝试了,是移动一个字节,其他编译器会怎样我也无法确定。 ↩︎

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值