本文章进一步的来讲解指针,如果是第一次接触指针的可以先看一下对于指针的初步理解
:
[C语言]初步的来了解一下指针(多图详解)_HY_PIGIE的博客-CSDN博客
目录
1.字符指针
2.指针数组
2.1指针数组:char*类型举例说明
2.2指针数组:int*类型举例说明
3.数组指针
3.1数组指针的定义
3.2数组指针与指针数组的比较
3.3“&”数组名与数组名
3.4数组指针的运用
3.5数组指针代码解析
4.数组传参,指针传参
4.1一级指针接收参数
4.2二级指针接收参数
5.函数指针
5.1函数指针的定义
5.2函数指针代码解析
6.函数指针数组
6.1函数指针数组的定义
6.2函数指针数组的运用
7.指向函数指针数组的指针
1.字符指针
字符指针:char*类型
对于char*类型的指针,之前所提到的是存放char类型变量地址的指针,或是本身为(1字节数)加上整数‘1’后跳过1个字节,解引用时同样的只有解锁1个字节的权限。
但char*类型还有另一个用法:用来存放字符串
对于这个常量字符串的打印:
printf("%s",a);//即可打印字符串“abcdef”
Q:可是指针为什么不用解引用呢?不应该是*a吗??
A:在char*类型指针中存放字符串,我们存放的是其首元素的地址,如果我们要打印字符串则是根据首元素的地址相应的打印整串字符。
既然a存放的是首元素‘a’的地址,那么相应的解引用*a则是根据a的地址找到对于的内容‘a’,打印的也只有a一个字符
第二个printf用%s打印会报错,更进一步证实了解引用*a得到的是‘a’单字符,而不是“abcdef”字符串
C/C++会把常量字符串存储到单独的一个内存区域,当几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。
2.指针数组
对于数组,我们之前认识的有:
int arr[]:整型数组,存放整型的数组
char arr[]:字符数组,存放字符的数组
而对于指针数组顾名思义,即是存放指针的数组:指针类型 arr[]
2.1指针数组:char*类型举例说明
对于指针数组的打印,像其他数组同样的打印方式:
for(int i = 0;i < 4;i++)
{printf("%s\n",arr[i]);
}
2.2指针数组:int*类型举例说明
对于其的打印有两种方式:
方式一:
for (int i = 0; i < 4; i++){for (int j = 0; j < 6; j++){printf("%d", *(arr[i]+j));//指针数组寸的是每个数组首元素的地址} //我们得到首元素地址后不断+1就可以得到后面的元素printf("\n");}
方式二:
for (int i = 0; i < 4; i++){for (int j = 0; j < 6; j++){printf("%d", arr[i][j]);}printf("\n");}
打印结果均为:
3.数组指针
3.1数组指针的定义
指针数组为存放指针的数组,那相应的数组指针:是一个指向数组的指针。
注意:‘[ ]’中的个数不能被省略
注意:“数组”的地址和“数组首元素”的地址,在数值上是相同的,但意义却是不同的。在数组首元素的地址上+1,会跳过一个元素的字节,得到第二个元素的地址。在数组的地址上+1,直接跳过整个数组的字节。
3.2数组指针与指针数组的比较
3.3“&”数组名与数组名
对于一个数组,我们知道arr是数组名,其还表示为一个数组首元素的地址。那&arr到底是什么呢??既然他有&取地址符号,是不是他也是一个地址呢??
int arr[4];
通过打印比较我们可以发现,他们所打印出的地址是一样的,都为数组首元素的地址,既然地址一样,就证明了他们是一样的吗??
答案是,不是的。arr与&arr只是在数值上相同,而代表的意义却大不相同。
下面会通过举例证明:
通过对比我们可以发现,arr与arr+1相差了4个字节。
而&arr与&arr+1相差了16个字节
&arr,为取数组的指针,那么其类型就为数组指针:int(*)[4],数组指针类型+1跳过的是整个数组(即:4*4=16字节数)。所以arr与arr+1、&arr与&arr+1分别的差值就会不相同。
3.4数组指针的运用
数组指针在一维数组上的运用较少,主要服务于二维数组,下面将通过举例说明其运用
二维数组函数传参,可以用使用指针接收,既然是接收数组的指针,自然是使用数组指针。
二维数组数组名是首元素地址,第一行的地址,相应的arr+1跳过16个字节,跳过第一整行,到达第二行第一个元素的地址
二维数组运用数组指针打印:
二维数组的数组名表示为首元素的地址,即第一行的地址。在数组指针接收的时候,得到的也只是第一行的地址,arr[3][5]中一行有5个元素,所以数组指针为int(*p)[5],表明的是一个指针指向数组的数组有5个元素。
//二维数组的打印//
void Printf(int(*arr)[4],int r,int c)
{for (int i = 0; i < r; i++){for (int j = 0; j < c; j++){printf("%d ", (*(arr + i))[j]);//也可以写成arr[i][j]} //(*(arr+i))等价于arr[i]printf("\n");}
}
int main()
{int arr[3][4] = { {1,2,3,4},{0,0,0,0},{2,3,3,3} };Printf(arr, 3, 4);return 0;
}
3.5数组指针代码解析
int(*parr[10])[5];
此代码表示的是,
parr[10]是一个数组,含有10个元素。
每一个元素的类型是:int (*) [5]
即为,一个parr[10]数组含有10个元素,每一个元素的类型是:int(*)[5],每一个元素都包含5个int类型
4.数组传参,指针传参
4.1一级指针接收参数
当函数的参数部分为一级指针的时候,函数能接收的参数有:
一维数组,一级指针的变量,与函数参数中一级指针指向的类型相同的地址。
void test(int* p)
{return 0;
}
int main()
{int a = 0;int arr[4];int *P = &a;test(&a);//与函数参数部分指针指向的类型相同的地址test(arr);//一维数组test(p);//一级指针
}
4.2二级指针接收参数
当函数的参数部分为二级指针的时候,函数能接收的参数有:
一级指针的变量的地址,二级指针的变量,指针数组。
void test(int** p)
{return 0;
}
int main()
{int *pa;int **ppaint* a[10];test(&pa);//一级指针的地址test(ppa);//二级指针的变量test(a);//指针数组
}
5.函数指针
5.1函数指针的定义
与前面介绍的数组指针格式类似,数组指针是指向数组的指针,则函数指针是指向函数的指针。
int add(int x,int y)
{return x + y;
}int main()
{int (*pa)(int,int) =&add;//函数指针int ret = (*pa)(3,2);printf("%d",ret);
}
函数名为函数区域块的首地址,所以我们在定义函数指针将函数地址赋给指针的时候可以不用取地址符号,相应的在使用函数指针的时候也可以直接使用,并不需要解引用。
下面举例证明:
int add(int x, int y)
{return x + y;
}int main()
{int (*pa)(int, int) = &add;int ret = (*pa)(3, 2);int (*pa2)(int, int) = add;int ret2 = pa(3, 2);printf("ret = %d\n", ret);printf("ret2 = %d\n", ret2);
}
打印结果:
5.2函数指针代码解析
代码1:
(*(void (*)())0)();
注意:void(*)()是一种类型
所以,此代码其实上是一个调用函数传参的。
代码2:
void (*signal(int , void(*)(int)))(int);
本代码为,signal函数的声明,函数参数分别为(整型,函数指针类型),函数返回类型为函数指针类型
函数指针类型:(指向函数的返回类型(*)(指向函数的参数类型);
可以看成:(但绝对不可以写成这种形式,这是错误的形式!!!!!!!!!)
void(*)(int) signal(int,void(*)(int));类型 函数
6.函数指针数组
看这个名字后缀,这东西肯定是一个数组,而且还是用来存放函地址的数组。
6.1函数指针数组的定义
函数指针数组,是一个函数指针类型的数组
函数指针类型:(指向函数的返回类型)(*)(指向函数的参数类型)
数组:数组名[存放元素个数]
结合起来就是:
(指向函数的返回类型)(*数组名[存放元素个数])(指向函数的参数类型)
6.2函数指针数组的运用
函数指针数组的用途:转移表
因为篇幅的原因,关于函数指针数组的运用将链接在下方
链接:[C语言]运用函数指针数组构建一个简单计算器_HY_PIGIE的博客-CSDN博客
7.指向函数指针数组的指针
即指向函数指针数组的指针。函数指针数组,既然是数组就可以取其地址来用另一个指针变量存放
其声明为:
定义其存放一个函数指针数组的指针:
int(*(*pp)[5])(int,int) = &p;
本文章完。
如果文章内有不对的地方欢迎留言指正,觉得本文章对您有帮助的话还请收藏留言点赞!感谢您的支持!