一,指针的概念
指针其实就是储存地址的一个位置,和我们定义的普通的常量取储存数据一样,二者只是储存的内容不相同,所以在使用指针的时候需要注意我们储存的具体内容,还有就是指针可以储存指针的地址,这就是双指针,就比较麻烦了。
二,指针的定义
指针指向的类型 *指针名
int *p;//指针叫做p,它是一个指向整型数据的指针,存放的也是整型数据的地址
//下面两个由于符号的优先级产生了不同的效果,[]都好的优先级高于*,所以优先进行结合
int *p[3];//指针叫做p数组,它是一个指向整型数据的指针,存放的也是整型数据的地址,数组是指针,所以我们把它叫做指针(的)数组,因为这个数组里面存放的全都是一些指针型变量,即一些地址
int (*p)[3];//这个是二维数组的指针,一个二维数组,他的行可以不确定,但是在存放元素时,他的列一定为定值,不然它可以在一行内无限的存入数据,那这就是一维数组了
int **p;;//这个就是比较复杂的的指针了,怕先于第二个*结合变成了一个指针,再与第一个*结合变成了指针的指针
这里我想强调一下二维数组,二维数组其实可以把他看作多个首地址逐次向后排,然后每一个首地址也都往后排入元素,这也是为什么要限制他的列数,否则第二个首地址无法确定,这样就不能存入数据
看到了指针如果没有出现[ ]我们就可以只看*,差不多就可以猜出来他是什么样的类型了,更具运算符的的优先级一层一层的分析
指针数组和数组指针的侧重点都在前面。指针数组是一个指针,存放的全都是指针(地址),数组指针就是一个单词的数组,用指针存放了这个数组的首地址
三,指针的简单运用
1,指针存取地址
int a,*p=a;
//注意我们这样写的前提是被取地址的变量需要先定义,只有当它被定义了,他的地址才会确定下来,我们才能使用指针进行存取
int *p,a;
p=&a;
*:这个符号标志着他是一个指针
&:取地址符号
int *p,a;指针和普通数据可以同时定义哦
p=&a;
//这里我要强调一下,p是地址,*p与a等价
scanf("%d",&a);
scanf("%d",p);
scanf("%d",&*p);
典例1:单个数据
#include<stdio.h>
int main()
{
int *p,a;
p=&a;
scanf("%d",p);
printf("%d %d\n",a,*p);
return 0;
}
输入:3
输出:3 3
p已经储存了a的地址,所以二者现在可以说连在一起了,所以a和*p在进行赋值时,二者是一样的
典例2:一维数组
数据倒置:
写法一:
#include<stdio.h>
void dao(int *p,int *q,int n);
int main()
{
int a[100],b[100],n,i;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
dao(a,b,n);
for(i=0;i<n;i++)
printf("%3d",b[i]);
return 0;
}
void dao(int *p,int *q,int n)
{
int i,j;
for(i=0,j=n-1;i<n&&j>=0;i++,j--)
*(q+i)=*(p+j);
}
写法二:
#include<stdio.h>
void dao(int *p,int n);
int main()
{
int a[100],n,i;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
da1(a,n);
for(i=0;i<n;i++)
printf("%3d",a[i]);
return 0;
}
void dao(int *p,int n)
{
int i,j,t;
for(i=0,j=n-1;i<=n/2&&j>=n/2;i++,j--)
{
t=p[i];
p[i]=p[j];
p[j]=t;
}
}
典例3:二维数组
二维数组的传递
#include<stdio.h>
void pr(int (*p)[100],int n);
int main()
{
int n,a[100][100],i,j;
scanf("%d",&n);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
pr(a,n);
return 0;
}
void pr(int (*p)[100],int n)
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf("%3d",(*(p+i))[j]);
printf("\n");
}
}
以上是一些整型数据的指针运用
在一维字符串数组里面,和一维数组一样,我们用指针标记他的第一个位置,然后其余依次往后推进,所以有一种写法*p="I LOVE CHINA!",而且他会主动地补入最后的‘\0'
二维字符串数组和普通类型的二维数组的用法一样,每一串字符的‘\0’也是自动补入
2,自定义函数指针
//函数指针变量的定义
int (* 指针名称 )(指向函数中形参的类型);
典例
函数的指针
#include<stdio.h>
int max(int a,int b);
int main()
{
int a,b,c;
int (*p)(int ,int );
p=max;
scanf("%d %d",&a,&b);
c=(*p)(a,b);
printf("%d\n",c);
return 0;
}
int max(int a,int b)
{
if(a>b)return a;
else return b;
}
//指针函数的定义
类型 *函数名(形参表)
{
函数体:
}
//注意,这里他的返回值是各指针,但是你用了*以后又会转化为普通的类型
典例
函数指针
整型数据
#include<stdio.h>
int main()
{
int *max(int ,int );
int a,b,c;
scanf("%d %d",&a,&b);
c=*max(a,b);//函数返回是a或者b的地址
printf("%d",c);
return 0;
}
int *max(int a,int b)
{
if(a>b)return &a;
else return &b;
}
字符串型
#include<stdio.h>
int main()
{
char *day(int);
char *p;
int n;
scanf("%d",&n);
p=day(n);//我们定义了一个指针去储存自定义函数返回的地址,注意我把,自定义函数前面的*删除了,如果不删除,那么此时的p是一个字符,而不会是一个地址
printf("%s\n",p);
}
char *day(int n)
{
static char *name[8]={"Error","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
return ((n<1||n>7)?name[0]:name[n]);//自定义函数返回的是一个植复仇的首地址
}
注意:这里的自定义函数似乎都没有提前声明,我的理解是它在main函数里面进行了说明
这里来聊一下指针数组和指针的指针,指针数组在前面的文章里讲过了,可以参考一下,这里就不在多说了
https://blog.youkuaiyun.com/weixin_61765266/article/details/122333631?spm=1001.2014.3001.5501
指针的指针:说简单一点就是一个指针指向了一个变量,但是这种指向也是有地址的,所以我们又用了一个指针去指向这个指针
#include<stdio.h>
int main()
{
char map[3][10]={"abc","def","ghi"},*a[3];
int i;
for(i=0;i<3;i++)
a[i]=map[i];
char **p;
p=a;
for(i=0;i<3;i++)
printf("%s\n",*(p+i));//依次输出p所指向的变量a所包含的内容,a内包含的是地址,所以直接输出一串字符
return 0;
}
我觉得这个指针有一点螳螂捕蝉黄雀在后的意思,不管你是啥,似乎总是有指针指向这个变量
注意一下*号的运用,这个东西一不小心就多了或者少了,那么指针指向的就不是变量了,指哪去就很神奇了,这也是指针一个比较难的地方
以上就是我对于指针的一些学习,里面可能部分是错的,欢迎各位大佬留言纠正