(硬核)C语言指针

目录

 

1、指针的概念

2、一级指针

2.1 一级指针的定义方式

2.2指针变量指向的类型的作用

2.3一级指针的使用

3、指针数组

3.1指针数组的概念

3.2指针数组的简单运用

4、数组指针

4.1数组指针的概念

4.2数组指针的简单使用

5、指针函数

5.1指针函数的概念

5.2指针函数的简单使用

6、函数指针

6.1函数指针的概念

6.2函数指针使用

7、函数指针数组

7.1函数指针数组的概念

7.2函数指针数组的简单使用

8、野指针 

8.1野指针的概念 

8.2消除野指针的方式                                                                                                                

9、二级指针以及多级指针 

9.1二级指针的概念

9.2二级指针的简单使用

题外话

本意是记录一下自己对指针的一些理解,以及希望通过自己的讲解,能够让各位初学指针的小伙伴更迅速的认识指针。这个是初版,后期会定期进行修改,有误的地方还请各位大侠指正,废话不多说,咱们直接进入正题。

1.指针的概念

那么什么是指针呢?指针就是地址,地址就是指针,一定要记住这个概念。要讲解指针,我们得从内存说起。把内存假想成一栋楼如下:

0x000000044
0x000000033
0x000000022
0x000000011
0x000000000

你家的楼总共有五间房间,每间房间有一个相应的门牌号0x00000000~0x00000004,每一间房间分别存放了0~4这五个数字。如果我们想要知道2在哪里,只需要告诉我们2对应的门牌号,那么我们就可以找到相对应的房间,进一步找到2, 对吧。这个门牌号就是我们所说的地址

咱们来看一个例题,在c语言中我们用&符号取变量的地址:

                                       

上图中,大家都知道num在内存空间占的字节数为4,四个字节各有一个地址,那么&取的究竟是哪一个地址呢?继续看上图我们令&num+1所跨越的字节数是4,也就是说,&取的是首地址,那么为什么取的是首地址呢?

举一个简单的例子,你的房间有100W,你给我说你的房间号0x62FE18,让我去打开你的房间拿钱,那我怎么知道0x62FE18房间号在哪里呢,你得告诉我你家的首地址我才能知道你家具体的位置,才能去到你家找到你的房间0x62FE18,是吧,那么是不是通俗易懂了呢,哈哈。

找到了你的房间,但是我又没有钥匙,我进不去你的房间呀,100W拿不出来,所以我得带一把钥匙 * ,这个符号是不是特别像钥匙呢,那我就用这把钥匙打开0x62FE18号房间的门,*(&num),得到的结果是100,是不是把钱取出来了,哈哈,结果如下图,请读者自行进行编程实践,实践见真知嘛:

                                           

 通过上面两个图做比较:num = *(&num),num是变量,而*(&num)是取&num这个地址空间里面的存放的值。

 接下来咱们继续看一个例子:   

              

可以直观的看到&num = p,也就是说指针变量p存储的是num的地址,所以指针就是地址,地址就是指针;而num 是等于 *p的,*p代表取p所指向的地址&num空间所存放的值,这样是不是就比较容易理解指针了呢?同学们。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

记住指针就是地址,地址就是指针。。。。。。。。。。。。。。。。。。。。。。。。。。。。

2、一级指针

2.1 一级指针的定义方式 

1.数据类型* 变量名称    2.数据类型 *变量名称;

2.2 指针变量指向的类型的作用

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int ret =0;       
	int num = 100;    //定义一个整型普通变量
	int *p = &num;    //定义一个指针变量并且该指针变量指向了num的地址
	printf("num的地址是:0x%X\n",&num);
	printf("p的值是:0x%X\n",p);
	printf("num的值是:%d\n",num);
	printf("*p的值是:%d\n",*p);
	exit(ret);
}

 2.2.1指针变量自身的类型

定义一个指针变量int *p,将指针变量去掉,剩下的是啥类型就是啥类型。p指向自身的类型是int *;

2.2.2指针指向的类型

定义一个指针变量int *p,将指针变量以及与离它最近的一个*去掉,剩下的是啥类型就是啥类型。p指向的类型是int ;

2.2.3指针变量所指向的类型有什么作用呢?

(1)决定指针变量+1的跨度,下面咱们来看一个示例:

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int ret = 0;
    int num = 100;
    int *p = &num;
    char *p1 = &num;
    printf("&num = 0x%x\n",&num);
    printf("p+1 = 0x%x\n",p+1);
    printf("p1+1 = 0x%x\n",p1+1);
    exit(ret);
}

在linux下输出为:                   

我们可以看到,p指向的类型是int,p+1的时候跨越了四个字节;而p1指向的类型是char,p1+1的时候跨越了一个字节,所以指针变量所指向的类型决定指针变量+1的跨度

 2.3一级指针的使用

例1:指针作为形参做一个简单的加法运算;指针作为形参改变主函数中普通变量的值

#include<stdio.h>
#include<stdlib.h>
void fun(int *p1,int *p2)//指针作为形参做加法运算 
{
	printf("%d\n",*p1 + *p2); 
}
void reform(int *num)//指针作为形参改变主函数定义的变量的值 
{
	printf("在函数内部的值:%d\n",*num);
	*num = 1000;
}
int main()
{
	int ret = 0;
	int m = 3;
	int n = 4;
	int num = 100;
	fun(&m,&n);
	reform(&num);
	printf("在主函数输出num的值:%d\n",num);
	exit(ret);
}

输出结果:

                      

当然以上指针的使用都特别简单,如果想更深入使用,请移步其他大佬的文章。

3、指针数组

3.1指针数组的概念

指针数组、是数组,是用于储存地址的数组,数组的每一个元素都是指针。定义的方式为:

数据类型 *指针变量[ ]。例如int *p[10]; 由于呢[ ]的优先级比*高,因此[ ]先和p组成数组,数组的每一个元素呢都是指针。因此指针数组是数组。

3.2指针数组的简单运用(低级用法)

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int ret = 0;
	//定义两个数组 
	char str1[] = "abcdefg";
	char str2[] = "hijklmn";
	//定义一个指针数组存放str1和str2这两个数组的首地址
	char *str3[] = {str1,str2};
	int i = 0;
	int j = 0;
	while(i<2)
	{
		while(j<sizeof(str1))
		{
			printf("%c",*(str3[i]+j));//输出指针数组所存放的值 
			j++;
		}
		printf("\n");
		j = 0;
		i++;
	}
	exit(ret);
}

输出结果为:

 首先明确str1和str2代表的是什么,str1代表的是str1这个数组的首元素的首地址,&str1代表的则是str1数组的首地址。。。。至于str3[i]+j的意思请移步2.2指针变量所指向的类型的作用。

4、数组指针

4.1数组指针的概念

数组指针是指针,定义的方式为:数据类型  (*变量名)[ ] ,例如:int (*p)[ 10 ],( )的优先级比[ ]高,因此p是指针,指向了有10个int类型数据的数组。

4.2数组指针的简单运用(低级运用)

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int ret = 0;
	//定义一个3*3的数组 
	int str1[9] = {1,2,3,4,5,6,7,8,9};
	
	int (*str3)[9] = &str1;
	int i = 0;
	int j = 0;
	while(i<1)
	{
		while(j<9)
		{
			printf("%d",(*str3)[j]);//输出指针数组所存放的值
			j++;
		}
		printf("\n");
		j = 0;
		i++;
	}
	exit(ret);
}

输出结果:123456789。当然有多种输出方式吗,我只是使用了其中一种。

5、指针函数

5.1指针函数的概念

指针函数是返回值为指针的函数,定义方式为:数据类型  *函数名();例如:int *fun(int *p);

5.2指针函数的简单使用

6、函数指针

6.1函数指针的概念

函数指针,本质是一个指针变量,该指针指向一个函数。总之,函数指针就是指向函数的指针。声明格式例如:类型说明符 (*指针变量)(函数入口参数),例如:int (*p)(int a,int b);

 6.2函数指针使用

需要将一个函数的地址赋值给指针变量

int (*p)(int a,int b);       int swap(int x,int y);           p = swap  或者  p = &swap;

以上取地址符不是必须的,因为一个函数 标识符 就表示了函数的地址,建议使用第二个方式。 函数指针在嵌入式中应用广泛,常常把函数指针作为结构体成员、作为函数的参数等。

程序示例如下图所示:

 函数指针作为结构体成员,作一个四则运算如下:

 函数指针作为函数的入口参数,作一个示例如下所示

 以上作为参数传递的函数指针通常表示回调函数(Callback Function): 什么是回调函数? 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

 7、函数指针数组

7.1函数指针数组的概念

和指针数组一样,函数指针数组是数组,数组中每一个元素是指针,是指向函数地址的指针,定义方式如下所示:数据类型   (*指针变量名[ ])();   

7.2函数指针数组的简单使用

#include<stdio.h>
#include<stdlib.h>
void fun1();
void fun2();
void fun3();
void fun4();
//定义一个函数指针数组 该数组有四个元素 每一个元素分别指向了函数的地址
void (*p[4])() = {fun1,fun2,fun3,fun4}; 
int main()
{
	int ret = 0;
	int m = 0;
	while(m<4)
	{
		(*p[m])();//逐个输出函数里面的内容 
		m++;
	}
	exit(ret);
}
void fun1()
{
	printf("我是第一个函数\n");
}
void fun2()
{
	printf("我是第二个函数\n");
}
void fun3()
{
	printf("我是第三个函数\n");
}
void fun4()
{
	printf("我是第四个函数\n");
}

输出结果:

 8、野指针

8.1野指针的概念

8.1.1.什么是野指针?

(1)定义指针并没有进行初始化,就被初始化为随机值,那么当对这个随机值进行访问的时候,这个时候这个值是不确定的,这就导致了野指针。

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int ret = 0;
	int m = 100;
    int *p; //并未进行初始化 
    printf("%d\n",*p);
	exit(ret);
}

(2)指针越界也会导致野指针的问题,越界之后访问的是非法的空间,也就导致野指针问题。

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int ret = 0;
	int arry[5] = {1,2,3,4,5};
    int *p = arry; 
    for(int i = 0;i<10;i++)
    {
    	printf("%d ",*(p+i));//指针越界 
	}
	exit(ret);
}

  (3)指针指向的空间被释放,导致野指针。

#include<stdio.h>
#include<stdlib.h>
int *fun()
{
       int a = 100;
       return &a;
	   //因为局部变量是在栈区开辟空的间 函数结束空间即销毁 
}
int main()
{
	int ret = 0;
    int *p = fun();//空间销毁 指针指向无效地址 
	printf("%d",*p); 
	exit(ret);
}

8.2消除野指针的方式

(1)声明指针变量的时候进行初始化  (2)指针不越界使用 (3)不使用指针的时候使指针指向NULL,指针指向NULL的方式有 free,delete。

9、二级指针以及多级指针   (这里以后再补充)                                                                         

9.1二级指针的概念 

9.2二级指针的简单使用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值