C语言指针与动态内存分配复习
C语言指针与动态内存分配复习
SmartSage一、引入
最近在学习数据结构,使用C语言来实现,经常用到指针相关的操作,而且还要频繁的动态分配内存,所以对指针以及动态分配内存的内容进行一下简单复习,方便后续数据结构的学习。
二、对指针的理解
指针其实也是一种变量,是一种特殊类型的变量,它存储的是变量的地址在32位系统中占用4个字节,在64位系统重占用8个字节。
三、指针的使用
定义一个指针
指针与其他基本数据类型的定义相似,也是需要指定类型,只有类型相同,指针才能操作它指向的地址。
例如:
1 | int a; |
从上边的程序可以看出,定义指针,其实就是在变量名前加一个*
使用指针
使用指针,需要用到*
运算符,来获取指针指向的内存上的数据。
1 | int a = 10; |
上面这是对于基本数据类型指针的使用,对于结构体指针的使用则需要用到->
运算符
1 | struct test |
说到结构体,还经常会有一种写法
1 | typedef struct test |
这种情况是使用typedef
给test
类型的结构体指针起了一个别名,这样以后再用这个指针的时候可以不加星号
1 | tset te; |
突然想到一些引用相关的知识:
1 | void add(int a, int b, int &sum) |
比如这样的一个函数,当我形参sum
前有一个&
符号,这里的&
符号并不是取地址的意思,而是C++中引用传递的意思,什么事引用传递呢。可以这么理解,C语言默认的是值传递,当调用函数的时候,知识将实参的值复制一份赋值给形参,在函数里是无法改变实参的值的,引用传递呢,就是给实参取了个别名,不是复制了一份,相当于我们在函数内其实就是在操作这个参数。
1 | add(10, 20, sum); // 调用方式 |
又想到一个点:
1 | typedef struct test |
分析一下,第一种,tt
其实是一种test
指针类型,我们传递的参数p
也是test
指针,所以是完全没问题的,那么为什么加了&
依然可以呢,因为引用,就是给变量起了个别名,也就是说我们这里的t
是p
的别名,p
的类型是test
指针,所以我们的函数用tt
类型的形参,所以直接t->a
也是没问题的。
指针与函数
函数名其实也是个地址,所以可以用指针来指向这个函数。
1 | int maxValue(int a, int b) |
四、内存分配
有四个函数:
1 | int *p = (int *)malloc(size); // 申请一块连续可用的空间,空间大小是size个字节,并返回指向这块空间的指针,注意是空指针 |
返回的是空指针,所以我们要转换一下类型,然后去接收它;
1 | void *calloc(size_t num,size_t size); // 为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0,返回值也是空指针 |
返回的是空指针,与malloc
同样的处理方式
1 | void free(void *memblock); |
释放内存,参数是一个指针,释放掉这个指针指向的内存。注意,它只能释放动态分配出来的内存,即只能释放堆区,而不能释放栈区的。释放内存后,并不会把他重置成空指针,此时它为野指针,指向一块不知道的内存,要及时将他重置成空指针。
1 | void *realloc(void *memblock,size_t size); // 为memblock指向的位置重新分配内存 |
这个是分情况的,如果memvlock
指向的那块空间后还有足够的内存,那么就会在后面继续分配,返回值与memblock
相同。
如果空间不够了,那么就会重新找一块足够的空间,先开辟出空间,再把原来的属于拷贝到新空间,然后释放原来的空间,同时返回这块新空间的地址。