多级指针
多级指针就是指向指针的指针,或者说是一个指针链,下面是一个程序示例以及它的运行结果。
#include <stdio.h>
int main() {
int num = 10;
int *num_p = #
int **num_p_p = &num_p;
printf("num的地址:%p\n", &num);
printf("*num_p的值:%p\n", num_p);
printf("*num_p的地址:%p\n", &num_p);
printf("**num_p_p的值:%p\n", num_p_p);
printf("num的值:%d\n",num);
printf("*num_p指向内存地址所对应的值:%d\n", *num_p);
printf("**num_p_p指向内存地址所对应的值:%d\n", **num_p_p);
}
![](http://upload-images.jianshu.io/upload_images/8917395-0e4a47b759e163ab.png)
运行结果
通过上面的代码可以看到,首先我们定义了一个 int 类型的变量
num
,并为它赋值为10,接着我们定义了一个 int 类型的指针变量num_p
并将num
的内存地址赋值给num_p
,再接着定义了一个二级int类型的指针变量num_p_p
并将num_p
的地址赋值num_p_p
。
多级指针示意图
数组指针
#include <stdio.h>
int main() {
int arr[] = {1, 6, 7, 8};
printf("&arr = %p\n", &arr);
printf("&arr[0] = %p\n", &arr[0]);
return 0;
}
![](http://upload-images.jianshu.io/upload_images/8917395-b65c3266f1f29aba.png)
运行结果
通过上面的运行结果可以看出,直接打印数组的内存地址是和其第一个元素的内存地址相同的,那么数组的指针其实就是数组第一个元素的指针,我们通过给指针做位移操作应该就可以拿到数组内的所有元素。
#include <stdio.h>
int main() {
int arr[] = {1, 6, 7, 8};
printf("数组的内存地址 = %p\n", &arr);
printf("数组第一个元素的内存地址 = %p\n", &arr[0]);
int *arr_p = arr;
/**
* sizeof(arr) 数组所占的字节数
* sizeof(int) int所占的字节数
* sizeof(arr) / sizeof(int) = arr数组的长度
*/
int index;
for (index = 0; index < sizeof(arr) / sizeof(int); ++index) {
// *(arr_p + index) :先挪动指针,然后再取出地址所对应的值
printf("位置:%d,值:%d,地址:%p\n", index, *(arr_p + index), arr_p + index);
}
return 0;
}
![](http://upload-images.jianshu.io/upload_images/8917395-765fb80416af3724.png)
运行结果
通过上面的运行结果可以看出,通过挪动数组指针确实可以拿到数组内所有的元素,细心的小伙伴可以发现,数组
arr
每个元素的内存地址都比其前一个元素大了 4,这个4就是int类型的元素所占的字节数量,所以我们也可以得出:数组是一块连续的内存地址。
指针挪动示意图
函数指针
在C语言万物皆指针,所以一个函数也有自己的内存地址,也有指针。
#include <stdio.h>
// C语言不支持函数的重载,所以声明函数时可以不用写形参
void add();
void sub();
void operation();
int main() {
printf("add函数的内存地址:%p\n",&add);
printf("sub函数的内存地址:%p\n",&sub);
operation(&add, 1, 1);
operation(&sub, 10, 1);
}
void add(int num1, int num2) {
printf("num1 + num2 = %d\n", (num1 + num2));
}
void sub(int num1, int num2) {
printf("num1 - num2 = %d\n", (num1 - num2));
}
/**
*
* @param method
* void 函数的返回值
* (*method) 函数的指针
* (int,int) 函数的形参类型
* @param num1
* @param num2
*/
void operation(void(*method_p)(int, int), int num1, int num2) {
printf("接收到函数的内存地址:%p\n", method_p);
method_p(num1, num2);
}
![](http://upload-images.jianshu.io/upload_images/8917395-d06a1c7263bb522f.png)
运行结果
这里我们定义了三个函数
add
、sub
、operation
,operation
函数的一个参数有些特殊,它接收一个 返回值为 void,形参为 int、int 的一个函数指针做参数,operation
函数拿到传递的函数指针,进而可以通过函数指针来调用相应的函数。
系统:Windows 10 64位
IDE:CLion