1、指针的内存分配
(1)指针定义时不会被分配内存,如int *p;
,如果指针没有初始化,会随机分配地址。
(2)指针初始化时,需要给其分配一个地址,如int *p = NULL;
或 int *p = &i;
。
(3)指针分配内存使用malloc
,位于堆区,用完需要free
。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
int i = 1; //全局变量分配内存在全局区
int *p = &i; //p指针指向i的地址
int *q = NULL;
printf("p(%p %d) i(%p %d)\n\n", p, *p, &i, i);
*p = 2; //改变p所指向地址的值,即改变了全局区的值
printf("p(%p %d) i(%p %d)\n\n", p, *p, &i, i);
p = (int *)malloc(sizeof(p)); //分配一块堆区,并把地址赋给p
printf("p(%p %d) i(%p %d)\n\n", p, *p, &i, i);
*p = 10; //改变堆区的内容
printf("p(%p %d) i(%p %d)\n\n", p, *p, &i, i);
q = p; //q和p都指向堆区
free(p); //**释放堆区(值被清空),p仍指向堆区**
printf("p(%p %d) q(%p %d)\n\n", p, *p, q, *q);
p = NULL; //p为空指针,q仍指向堆区
printf("p(%p) q(%p)\n\n", p, q);
return 0;
}
执行结果:
p(0x7ffffc0473fc 1) i(0x7ffffc0473fc 1) //p指向i的地址,故打印一样
p(0x7ffffc0473fc 2) i(0x7ffffc0473fc 2) //全局区被改变了,故p和i均改变
p(0x1f47e80 0) i(0x7ffffc0473fc 2) //i仍为全局区,p指向堆区
p(0x1f47e80 10) i(0x7ffffc0473fc 2) //堆区内容被p 改变,值改变
p(0x1f47e80 0) q(0x1f47e80 0) //堆区被free
p((nil)) q(0x1f47e80) //p为NULL,q仍指向堆区
2、结构体指针的内存分配
#include <stdio.h>
#include <stdlib.h>
typedef struct example
{
int *a;
int b;
}example_t;
int main(int argc, char** argv)
{
int *p;
int i = 1;
example_t *exam;
printf("exam(%p %p) p(%p %p)\n\n", &exam, exam, &p, p); //exam和p都是(结构体)指针变量,&p为全局区指针变量的地址,p为指针变量的值
exam = (example_t *)malloc(sizeof(example_t)); //堆区分配空间,并赋值给exam
if(NULL == exam)
{
printf("%s\n", "exam malloc failed");
return -1;
}
printf("exam(%p) a(%p %p) b(%p %d)\n\n", exam, &exam->a, exam->a, &exam->b, exam->b);
//结构体指针成员:指针变量a的地址存在,但其值为NULL;变量b的地址存在,其值未初始化为随机
exam->b = i; //将全局区i 的值拷贝给堆区b,后操作b,不会影响i
exam->a = (int *)malloc(sizeof(int));
*exam->a = 3;
printf("exam(%p) a(%p %p %d) b(%p %d) i(%p %d)\n\n", exam, &exam->a, exam->a, *exam->a, &exam->b, exam->b, &i, i);
//分配了堆区,并把值赋给a,故a的值存在,a指向的堆区的值也存在
free(exam->a);
printf("exam(%p) a(%p %p %d) b(%p %d) i(%p %d)\n\n", exam, &exam->a, exam->a, *exam->a, &exam->b, exam->b, &i, i);
//a被free后,a仍指向堆区,只是堆区的内容被清理了
exam->a = NULL;
printf("exam(%p) a(%p %p) b(%p %d) i(%p %d)\n\n", exam, &exam->a, exam->a, &exam->b, exam->b, &i, i);
//指针变量a的地址不变,但其值为NULL;此时再访问*exam->a就会报代码段错误
free(exam);
printf("exam(%p) a(%p %p) b(%p %d) i(%p %d)\n\n", exam, &exam->a, exam->a, &exam->b, exam->b, &i, i);
//free:指针变量a的地址不变;b的地址不变,值被清理为随机,i不受影响
//疑问:a的值为什么又不为NULL了
//exam = NULL;
printf("exam(%p)\n\n", exam);
return 0;
}
执行结果:
exam(0x7fff0f2d1d38 (nil)) p(0x7fff0f2d1d48 0x401070)
exam(0x15e8e80) a(0x15e8e80 (nil)) b(0x15e8e88 0)
exam(0x15e8e80) a(0x15e8e80 0x15e8ea0 3) b(0x15e8e88 1) i(0x7fff0f2d1d44 1)
exam(0x15e8e80) a(0x15e8e80 0x15e8ea0 0) b(0x15e8e88 1) i(0x7fff0f2d1d44 1)
exam(0x15e8e80) a(0x15e8e80 (nil)) b(0x15e8e88 1) i(0x7fff0f2d1d44 1)
exam(0x15e8e80) a(0x15e8e80 0x15e8ea0) b(0x15e8e88 22896656) i(0x7fff0f2d1d44 1)
exam(0x15e8e80)
3、指针变量当做数组运用
C语言指针变量可以当做数组运用,在应用之前,应该先让指针指向一个数据块,可以是程序中的某个数组(这个就不说了),也可以指向一段新分配的内存空间;例如:
#include <stdio.h>
#include <stdlib.h>
int main(){
int i,*p;
p=(int *)malloc(sizeof(int)*10); //分配10个整数的存储空间,p指针指向该空间
for(i=0;i<10;i++)
p[i]=i; //象平常数组一样访问p指向的存储空间
for(i=0;i<10;i++)
printf("%d ",p[i]);
free(p); //释放p指向的存储空间。
}
如果指向新的内存空间时,特别是在子函数中,注意灵活处理要不要释放该存储空间。