各位老板、打工人们,下午好。我是“大怨种”,21届毕业生。工作了一年,放弃了稳定还不累的电气设计工作,选择转行,想进入软件行业,本打算自学编程语言的基础--C语言。奈何大学时C语言课程没有好好听讲,外加工作一年没碰相关知识,C语言早都忘得一干二净。就从网上找了教程自学习,后来发现自学,学是能学懂,但是只是些浅浅的皮毛。就打算报个班学习一下,偶然机会知道了华清远见这个教学机构,就抱着试一试的态度去参加了培训。现在上课已经有快一个月了,感觉还不赖,老师的水准特别高,讲课通俗易懂。
以后的3个多月,我会写一些我自己的C语言、C++还有其他课程的知识点总结,也可能会写一些电气设计行业的一些心得和潜规则,希望对迷茫的”电气人“毕业生们提供一点小小的帮助。
言归正转,这篇帖子我想总结一下指针、数组指针、指针数组、二级指针、指针函数、函数指针。
一、 首先是指针的祖宗-------一级指针;
1、指针的定义(自己总结的,非官方解释):存放地址的变量叫指针。通俗点讲,这个变量是放其他变量或者内存空间的地址的。
2、 指针有两大关注点,指针的类型,指针的指向类型。例如定义一个指针变量p存整形变量a的地址:int a; int * p=&a; 指针p的类型是int*,指向的类型是int
3、通过指针变量p去访问指向的变量a:用*p,现在这个*p==a; 改变*p和a之间的谁,另一个也跟着改。
4、上面说的第三点主要应用在函数的传参作用。一个函数要改变a的值,不能直接改a的值,要通过a的地址去改变。
5、指针和数组: 先定义一个数组int a[5],数组的名字就是该数组的首地址。我的理解是数组的名字a是一个指针变量(当然a不是),这个指针变量存的是int [5]这个一维的无名的数组首地址。那么 int* p=a;------------>相当于两个指针变量之间的赋值,地址的复制,传递。
6、指针、数组与加1: int a[5] ; int* p=a ;那么p+1----->可以理解为p原来指向数组的首地址,它加1个,记住不是地址字节加一,是变量加一,相当于地址字节加4(int是4个字节)。那么自然原来p指向a[0],变成了p+1指向a[1],但实际p还是指向a[0]
7、指针int a[4], int* p=a; p++ --------------->代表的是p=p+1;指针变量加一之后,赋值给本身,p的指向变了,变成指向a[1]; a++-------->报错,语法错误。
8、指针与数组的重要连等式: int a[10]={0}; int* p= &a;i是变量,用i代表数组10个元素脚标
表示地址 a+i==p+i==&a[i]==&p[i] 表示元素a[i]==p[i]==*(p+i)==*(a+i)
9、*p++ 和 *++p的区别: 首先要清楚* 和++ 都是运算符,和数学里面一样,计算是由优先级的,*和++ 优先级为同级别2,但是它们遵循从左往右计算。所以都是先看p++或者++p ,之后再考虑取值运算*的结果。
二、 数组指针之-------------指针的小弟,数学是不会骗人的
数组指针都叫指针了,那么本质上是指针,所以要关注他的指针类型和指向类型。
先定义一个数组指针,有个直观的感受: int (*p)[5]---------->这是一个指向一维数组的指针变量p。
开始解释: ()、[]、*这三个是运算符,遵循数学规律,优先级问题。()、[]为一级,*为二级。一级别的运算符和二级的不一样,同级别按照从左往右的顺序依次计算。(*p)--->代表这是个指针。int [5]---------->代表这是个元素类型为int,元素个数为5的无名一维数组。所以指针变量p的类型为int(*)[5], 指向类型为int [5]。指向了一个一维数组。
那么学习这个有啥用? ---------------为了在函数运行中进行二维数组的传参。下面简单的说下二维数组的理解。
<-------------------------------讲个简单的应用-------------------->
二维数组传参到函数,传的还是数组的首地址,它可以是二维数组的名,也可以是a[0]。
#include<stdio.h>
void my_hS(int(*p)[4],int n)
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<4;j++)
{
printf("%d",p[i][j]);
}
printf("\n");
}
}
int main(int argc, const char *argv[])
{
int b[3][4]={{1,1,1,1},{2,2,2,2},{3,3,3,3}};
my_hS(b,3);
return 0;
}
支线任务一:二维数组的解释之-----------我的爸爸是一维数组
二维数组可以看成是一维数组组建构成的,例如:二维数组的a[3][4],第二个脚标代表列数(人为的把它当成矩阵看,其实不是矩阵),上面的二维数组a,它是由一维数组a[3]构成。现在这个a[3]不是元素了,是名字。
三 、指针数组之--------------我和指针不是一家的,他是指针,我是数组,他姓指,我姓数
指针数组,本质上是数组,定义一个数组,里面存的是指针。
定义个数组,举个例子:int *p[3], 老规矩,数学是不会骗人的,[]优先级一级,*优先级二级。p和[3]是一家的,是个数组,元素个数是三。int*是一家的表示数组里面存的是指针。
讲完了。。。。下面举个小栗子浅浅的体会下:
----------------------------------->举个例子<----------------------------------
#include<stdio.h>
int main(int argc, const char *argv[])
{
char a[]="hello";
char b[]="hi";
char c[]="bye";
char* p[3]={a,b,c}; //存了三个地址,也可以说存了三个指针变量
int i;
for(i=0;i<3;i++)
{
puts(p[i]);
}
return 0;
}
四、二级指针之---------------------俄罗斯指针套娃
讲个故事,从前有个n级指针它是个俄罗斯套娃,里面套了个n-1级指针,n-1级指针套了个n-2级指针........2级指针套了个1级指针,1级指针套了个猴子(其他变量、函数等等的地址)。
首先我们要明确,指针无论是几级的里面存的东西都是个地址。
举个例子:int a=10; int* p= &a; int** s =&p; ----->首先p这个一级指针存的是变量a的地址。指针变量p也是变量啊,它也有它自己的地址,那就是&p ,二级指针就是存一级指针的地址的。特别说明,改变*p的值就相当于改变a的值,改变*s就相当于改掉一级指针p的指向。
几个重要等式:**s==*p==a ==10-----------里面是值 *s=p=&a 指向a的地址
s=&p s指向p的地址
------------------------------->举个小小的例子<-----------------------------------
#include<stdio.h>
#include<stdlib.h>
void my_dongT(int **s)
{
*s=malloc(4*sizeof(int));
if(*s==NULL)
{
printf("申请空间失败\n");
}
}
int main(int argc, const char *argv[])
{
int i;
int *p; //现在我要改变p的指向
my_dongT(&p);
for(i=0;i<4;i++)
{
p[i]=i;
}
for(i=0;i<4;i++)
{
printf("%d\n",p[i]);
}
free(p);
return 0;
}
五、函数指针---------之我姓指,不姓函,并且数学不是骗人的
函数指针,本质是个指针,要研究它的指针类型和指针指向类型。
定义个函数指针,举个例子:int (*p)(int int ),这个指针名叫p,指向的类型是int (int int)返回值类型是int,两个参数为int的函数。这个指针存的是一个函数的地址,函数的名字就是该函数的首地址。
----------------->举个例子加法<-----------------
#include<stdio.h>
int my_jia(int a,int b)
{
return a+b;
}
int main(int argc, const char *argv[])
{
int (*p)(int, int)=my_jia;
printf("%d\n",(*p)(3,5)); //*p代表,顺着p里面存的地址把函数my_jia调用出来。
// 上一句也可以写成printf("%d\n",p(3,5)); //这直接把p和my_jia等价了.
return 0;
}
ps:重要说明:int my_jia(int a,int b) int (*p)(int, int)=my_jia; ----->相当于p=my_jia;
my_jia是函数的首地址吧,p也是,所有p和my_jia都指向这个函数,所以可以直接用
调用时候可以写 (*p)(3,5)=========p(3,5)
六、指针函数----------之我是函数,不是指针
指针函数,本质上是个函数,他的返回值类型是指针:
定义个指针函数,举个例子: int* num(int a,int b),这个函数的意思是参数类型为2个int型,返回值类型是个int*,是个地址。那么主函数或者其他函数接受其返回值的变量肯定是个指针!!
------------------------------>举个例子查找字符串中字符是否存在,存在返回其地址,打印<-------------
#include<stdio.h>
char* is_within(char* s,char ch)
{
int i=0;
while(s[i]!='\0')
{
if(s[i]==ch)
return &s[i];
i++;
}
return NULL;
}
int main(int argc, const char *argv[])
{
char a[100]="hello";
char* p=is_within(a,'l');
if(p==NULL)
{
printf("没有找到\n");
}
else
{
printf("找到了\n");
}
return 0;
}
以上的内容,纯属自己的理解,如果和官方解释有冲突的,请以官方为主,其中有不妥的或者错误的地方,请评论区狠狠的喷我,给我指出来,让我长长记性。
最后祝大家早日成神。