在前面的指针是个什么针?这篇文章中已经写了指针的基础知识,然后通过这篇文章来对指针进行更深层次的理解
目录
一、字符指针
字符指针的创建也是挺简单的,char*类型一次最多可访问一个字节的空间
请看如下代码:
#include <stdio.h>
int main()
{
char s = 'm';
char* ps = &s;
printf("%c\n", *ps);
*ps = 'w';
printf("%c\n", *ps);
return 0;
}
这就是指针的创建以及访问操作,运行结果如下:
关于字符指针这边主要想说的就是下面这种情况
int main()
{
char* p = "abcdef";
}
这是将字符串"abcdef"存到了指针p里面了吗?
abcdef总共7个字节大小,而char*在32位平台才4个字节,是根本存不下的,所以不是直接将整个字符串存到了指针p里面
要注意这种写法是将这个字符串的首字符地址给了p
这种写法也还不太严谨,在有的编译器下是会报错的,再修改一下
int main()
{
const char* p = "abcdef";
}
二、指针数组
顾名思义,指针数组就是存放指针的数组
再看看下面代码中的数组
int* arr1[6]; //整形指针的数组
char* arr2[8]; //一级字符指针的数组
char** arr3[7]; //二级字符指针的数组
下面创建整型指针数组
#include <stdio.h>
int main()
{
int a = 0;
int b = 1;
int c = 2;
int* arr[3] = { &a,&b,&c };
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d ", *arr[i]);
}
}
这里是创建了一个整型指针数组,并对它进行了初始化,里面存放有a,b,c的地址,再通过解引用去打印出a,b,c
运行结果:
如下图:
这个数组里面每个元素都是一个整型指针
通过下面这段代码再加深一下理解
#include <stdio.h>
int main()
{
int arr1[] = { 1,2,3 };
int arr2[] = { 4,5,6 };
int arr3[] = { 7,8,9 };
int* arr[] = { arr1,arr2,arr3 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 3; j++)
{
printf("%d ", arr[i][j]);
}
}
return 0;
}
通过这段代码创建指针数组,并对它进行访问,打印操作
三、数组指针
数组指针是一个指针,指向数组的指针,里面存放数组的地址
数组指针的形式如下:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;
}
这里的p首先和*结合,说明它是一个指针,指向的是什么呢?指向了一个数组,数组10个元素,每个元素的类型都是int
数组名和&数组名
数组名是数组首元素的地址,&数组名是取出整个数组的地址
请看如下代码:
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
printf("%p\n", &arr);
return 0;
}
运行结果:
通过这个运行结果会发现这三个打印出来的值是一样的
那难道数组名和&数组名真的就一样吗?我们通过以下代码再来看看:
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%p\n", arr);
printf("%p\n", arr + 1);
printf("%p\n", &arr);
printf("%p\n", &arr + 1);
return 0;
}
运行结果:
可以看到在给&arr和arr分别+1之后打印出来的结果是不一样的,arr+1跳过了1个整形4个字节,而&arr+1是直接跳过了整个数组
数组指针的使用
数组指针的使用一般常用于二维数组
如下代码:通过数组指针来访问二维数组
#include <stdio.h>
print(int (*p)[5], int x, int y)
{
int i = 0;
for (i = 0; i < x; i++)
{
int j = 0;
for (j = 0; j < y; j++)
{
printf("%d ", (*(p + i))[j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };;
//通过下面这个函数以指针形式来访问数组
print(arr, 3, 5);
}
运行结果:
四、函数指针
函数指针就是指向函数的指针 ----存放函数的地址
函数地址
我们可以先通过下面的代码来体验一下:
#include <stdio.h>
void test()
{
}
int main()
{
printf("%p\n", &test);
}
运行结果:
这里打印出了函数的地址
要知道数组名表示的是数组首元素的地址,那么函数名会不会也是函数的地址呢?
通过以下代码来验证一下:
#include <stdio.h>
void test()
{
}
int main()
{
printf("%p\n", &test);
printf("%p\n", test);
}
可以看到打印出来的结果是一样的,所以就可以确定函数名表示函数的地址
函数名与&函数名都是函数的地址,没有区别
函数指针创建
如下代码:
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
int (*ps)(int, int) = Add;
return 0;
}
这里的*p说明ps是一个指针,后面的(int,int)说明这个指针是指向一个函数,前面的int说明这个函数的返回值是int
函数指针的使用
我们可以通过函数指针来调用所指向的函数
如下代码:
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
int (*ps)(int, int) = Add;
int add = (*ps)(1, 2);
printf("%d\n", add);
return 0;
}
运行结果:
其实我们把Add放在了ps里面,那么其实ps和Add应该是一样的,用到的*其实在这里并没有什么实际作用,我们也可以用下面的写法
int add = ps(1, 2);
五、函数指针数组
里面存放函数指针
如下代码:
int add(int x, int y)
{
return x + y;
}
int sub(int x, int y)
{
return x - y;
}
int main()
{
//函数指针数组
int (*pf[5])(int, int) = { add,sub };
}
以上代码中的就是函数指针数组
pf[5]表示它是一个数组,剩下的部分说明它里面的每个元素都是函数指针,所指向的函数都是两个int类型的参数,返回类型位int
函数指针数组主要用于转移表
之前在C语言实现简易计算器这篇文章中写了函数指针数组的用法,用转移表来实现简易计算器,欢迎大家阅读,这里就不再把那个代码搬过来了
六、指向函数指针数组的指针
这是一个指针,指针指向一个数组,数组里面的每个元素都是函数指针
因为指向函数指针数组的指针用的非常少,所以这里就不再展开介绍了
如下代码示例:
int (*psa)(int, int); //函数指针
int (*ps[5])(int, int); //函数指针数组
int (*(*pps)[5])(int, int) = &ps; //指向函数指针数组的指针
注意:这里怎么判断是哪一种类型的指针,主要还是看的是操作符的结合性与优先级问题
-----------------------------------------------------------------
-----------------C语言指针进阶部分完结-------------------
关于C语言,每个知识点后面都会单独写博客更加详细的介绍
欢迎大家关注!!!
一起学习交流 !!!
让我们将编程进行到底!!!
--------------整理不易,请三连支持------------------