最详细的C语言指针进阶讲解

C语言指针可以说是C语言的精髓,看一个人是否熟练掌握C语言,就看他对C语言指针的理解程度。



整形指针

#include<stdio.h>
int main()
{
	int a = 10;
	int* p = &a;
	*p = 6;
	printf("%d\n",a);
    return 0;
}

请添加图片描述
这就是较为简单的C语言指针了,取出地址存储在指针,再经过解引用修改该地址上的数据。



字符指针

int main()
{
    char ch = 'w';
	char* pc = &ch;
	char* ps = "abcdef";
	return 0;
}

指针pc存储字符变量的地址,通过解引用也可以修改该地址上的数据。

对于指针ps,有个小知识点,当字符指针要存储的是字符串时,字符指针会存储字符串的首个字符的地址,并且可由首个字符的地址找到接下来的所有字符的地址并修改。



指针数组

指针数组顾名思义就是存放着指针的数组。

#include<stdio.h>
int main()
{
	char* arr[] = {"zhangsan","lisi","wangwei"};
	int i = 0;
	for(i=0;i<3;i++)
	{
	    printf("%s\n",arr[i]);
	}
    return 0;
}

当然,在这个字符指针类型的指针数组中,存放的依然是每个字符串的首个字符地址,可以通过首个字符的地址找到后面的所有字符。

运行结果如下:

请添加图片描述

数组指针(存放数组的地址)

数组指针顾名思义就是存放数组地址的指针。

#include<stdio.h>
int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int (*p)[10] = &arr;
    return 0;
}

p就是一个数组指针。



数组指针的用处

数组指针在一维数组的应用

#include<stdio.h>
void print(int (*p)[10],int sz)
{
    int i = 0;
	for(i=0;i<sz;i++)
	{
	    printf("%d ",(*p)[i]);
	}
	printf("\n");
}
int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int sz = sizeof(arr)/sizeof(arr[0]);
	print(&arr,sz);
    return 0;
}

运行结果如下:
请添加图片描述
取出整个数组的地址,传给print函数的数组指针参数,解引用找到数组名,再通过【】找到相应的元素。但是,这里有点搞复杂,原本传过去就可以是数组名,再通过【】找到相应的元素,更加简便。数组指针更适合在二维数组使用。

数组指针在二维数组的应用

#include<stdio.h>
void print(int (*p)[5],int r,int c)
{
	int i = 0;
	int j = 0;
	for(i=0;i<r;i++)
	{
	   for(j=0;j<c;j++)
	   {
	       printf("%d ",*(*(p+i)+j));
	   }
       printf("\n");
	}
}
int main()
{
	int arr[5][5] = {{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7},{4,5,6,7,8},{5,6,7,8,9}};
	int sz = sizeof(arr)/sizeof(arr[0]);
	print(arr,5,5);
    return 0;
}

运行结果如下:
请添加图片描述
在这里需要注意的是,传参给print函数的数组指针参数时,并没有取出整个数组的地址,而是数组名。这里有个小知识点,二维数组的数组名是首元素的地址,而二维数组的首元素就是二维数组的第一行,本身就是个一维数组,也就满足了数组指针p的条件。

(p+i)再经过解引用是找到某一行的数组名。前面讲过,数组指针接受的是二维数组的第一行,加一就来到第二行,再加一就来到了第三行。

(*(p+i)+ j)再经过解引用,找到某一行的某一个元素。

如 i 为 0 时,p+i找到第一行的地址也就是第一行第一个元素的地址,在经过加 j 找到某个元素的地址。

如下图:
请添加图片描述

函数指针

函数指针是一个接受函数地址的指针,在讲函数指针时,先引入一个知识点,函数名与取出函数的地址的结果是相同的。验证如下:

#include<stdio.h>
int Add(int x,int y)
{
    return x + y;
}
int main()
{
    printf("%p\n",Add);
	printf("%p\n",&Add);
    return 0;
}

运行结果如下:
请添加图片描述
由结果可以得知,两个打印的地址完全相同,函数名与取出函数的地址的结果是相同。

#include<stdio.h>
int Add(int x,int y)
{
    return x + y;
}
int main()
{
	int ret =  0;
	int (*p)(int,int) = Add;       //声明返回类型和参数类型
	ret = (*p)(3,5);               //传参要计算的值
	printf("%d\n",ret);
    return 0;
}

运行结果如下:
请添加图片描述

函数指针数组

函数指针数组可以存放多个(参数相同,返回类型相同)的函数的地址。

#include<stdio.h>
int Add(int x,int y)
{
    return x + y;
}
int sub(int x,int y)
{
    return x - y;
}
int main()
{
	int ret = 0;
	int (*p[2])(int,int) = {Add,sub};
	ret = p[0](3,5);
	printf("%d\n",ret);
	ret = p[1](3,5);
	printf("%d\n",ret);
    return 0;
}

请添加图片描述

指向函数指针数组的指针

//函数指针
int (*ptr)(int,int);

//函数指针数组
int (*arr[10])(int,int);

//指向函数指针数组的指针
int (* (*p)[10])(int,int) = &arr;

关注点一点,下期更精彩。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值