一、如何获得合法内存
在C语言初学阶段,我们有两种方法申请合法内存:
(1)直接定义变量,可以是全局变量,局部变量,静态变量。
(2)调用malloc系列函数管理内存。
二、堆内存使用
(1) void *p 解释。
对于type *p 来说 ,*前面的type 决定了 *p的时候做的事情,见 http://blog.csdn.net/xiaoliu0518/article/details/32707111
对于void *p来说,p只是记录一个地址,不做 *p解析。
对于任何指针变量来说,都是用来存储地址,因此 任何指针变量 之间赋值 都不会出现数据的丢失,见如下代码:
void *p1;
char *p2;
int *p3;
p1 = p2;
p3 = p2;
理论上,这样去写没有问题:
但是第5行会有警告,而第4行没有警告。
警告的原因在于对于 char *p2 ,char *p3 ,都会去做 *p2 ,*p3 这种操作,做这样操作的时候,*p2访问一个字节,*p3访问4个字节,如果p2存储的地址开始如果只有1个字节有效内存的话,*p2没问题,但是*p3就会访问到非法内存,因此可能导致错误,你不确定一个地址开始多少字节是有效的时候,去做*p操作是有危险的。
而 p1 = p2没警告,是因为对于 void *p1,来说,p1只记录地址,不做*p1操作。
(2) malloc函数
void *malloc(size_t size);
void free(void *p);
malloc 的参数是非负整数,这里size_t 由 typedef unsigned int size_t,或者 typedef unsigned long size_t而来。
malloc 在堆中申请 size 个字节大小的内存,并且把这块内存的首地址返回出来,申请失败返回 NULL,NULL的数值为0 ,其实是(void*)0.
free 参数是 malloc返回出来的地址,释放掉申请出来的内存。
注意,堆内存的申请释放由自己管理,申请得到后,用完一定要记得释放。
void *p;
p = malloc(20);
对于以上代码,假定已经申请成功,p存储了合法有效的地址,并且从这个地址开始20个字节的内存是可以使用的。
那么我既可以给这20个字节内存里存储20个char数据,也可以存5个int数据。
int *p1 = (int*)p;
char *p2 = (char*)p;
int i = 0;
for(i = 0;i<20;i++)
{
*(p2+i) = 'a';
}
for(i = 0;i<5;i++)
{
*(p1+i) = 1;
}
通过指针变量如何访问所指向的内存,完全取决于 指针变量 定义type* p,type决定了*p的方式。
写完整代码测试如下:
#include <stdio.h>
#include <malloc.h>
int main()
{
int *p = NULL;
int *p1 = NULL;
char *p2 = NULL
int i = 0;
p = malloc(20);
if(p == NULL)
{
//申请失败
return 1;
}
p1 = (int*)p;
p2 = (char*)p;
for(i = 0;i<20;i++)
{
//这里是不是很眼熟? *(p2+i), 试试 p2[i]
*(p2+i) = 'a';
}
for(i = 0;i<20;i++)
{
printf("%c",*(p2+i));
}
for(i = 0;i<5;i++)
{
//这里是不是很眼熟? *(p1+i), 试试 p1[i]
*(p1+i) = 1;
}
for(i = 0;i<5;i++)
{
printf("%d\n",*(p1+i));
}
//注意用完不要忘记free
free(p);
return 0;
}
根据以上代码,发现malloc的内存可以当数组来使用,其实数组的本质是连续的内存,malloc 是申请一片连续的内存,所以当听到 动态数组的是概念的时候其实就是malloc。
以下的写法可以让别人跟清楚得指导你的意图
int *p;
p = (int*)malloc(sizeof(int)*10);
这里很明显,大家知道你要给这片内存中存10个int数据了。