目录
指针作为c语言的核心,弄清楚什么是指针,指针的作用是什么,对学习c语言尤为关键。
一、了解指针
1.1 什么是指针
在c语言中,通常以下这种形式来表示一个指针:
int a = 10;
int* pa = &a;//&号作用是取出a的地址 *号表示pa是一个指针
上面程序中,a是一个变量,a所存储的数据是10,他的类型是int。
同理,pa是一个指针变量(也就是指针),他所保存的数据是a的地址,他的类型是int *。
1.2 为什么需要指针
在计算机中,有32/64根地址线,这些地址线会产生高、低电平两种物理状态,转换成数字信号即为0、1,也就是我们熟知的二进制。因此在32位机器上可以产生2^32次方不同的二进制序列,这些不同的二进制序列就可以构成唯一的地址号,每个地址管理着1个字节(8bit)的内容。
计算机把各种数据都存储在这唯一的地址号中,这时候可以通过指针来获取这些数据的地址号,也可以通过指针来找到这些数据,对他们的数据进行相关修改,极大的提高了代码的灵活性、程序的执行效果。再者,指针可以直接访问内存的地址,进行的是底层操作,因此还可以与硬件实现交换。
1.3 指针的作用
指针可以理解为是一个指向某处的标识符,他跟路标的作用一样,就是可以根据这个路标找到某处。
在c语言中,因为指针存储的是地址,因此可以通过指针找到某个变量,从而访问该变量的数据。 如下,因为pa是一个指针,他保存的是地址,因此可以通过对pa进行解引用操作(*),从而访问a的数据。
还可以通过指针pa,达到对a数据的间接修改。
可以看到,a的数据变成了20,因此可以理解为:*pa就是a。
1.4 指针类型的区别
在c语言中存在多种的数据类型,比如:char、short、int、longlong、double....这些类型构成了丰富的数据,每种类型的功能也各不相同。
在指针中也存在类型,比如:int类型的指针,char类型的指针,不同类型的指针解引用后所能访问的权限大小不相同。
从上面程序中可以得知,用char类型的指针保存变量a的地址,然后对其进行解引用(*)访问a的数据时,只能访问a中一个字节的内容(小端模式低位放在低地址处,44是a的二进制序列中的低位,因此在内存中44是放在低地址处,*pc从低地址开始访问一个字节,因此*pc=44)。而int型指针pa解引用后能访问a中的全部内容。
int型指针解引用后所能访问的权限大小是4字节,char型指针权限大小是1字节。因此在保存变量地址时,指针类型要与变量的类型对应起来,在解引用时才能访问完整的数据,否则会发生数据的丢失或者越界访问随机数据。
1.5 指针的大小
影响指针大小只有一个因素:机器的位数(32位/64位),因为指针所保存的是地址。在32位机器上,地址是由32根地址线转变数字信号所产生的,因此地址号是由32个bit位组成的,32个bit位=4个字节,如果想把这4个字节的内容存起来则需要4个字节的空间,因此不管是什么类型的指针,地址都是由32位bit位组成,大小都是固定的4字节。64位机器上同理。
1.6 指针的运算
一般是用于访问数组中各类元素的,从物理的角度来看就是指针不断往后移动,然后解引用访问该元素的值。
指针-指针可以求出指针之间的元素的个数, 比如:&arr[4] - &arr[0]是得出第一个元素的地址与最后一个元素的首地址之间的元素个数。
1.7 二级指针
指针本身也是需要开辟一个空间用于保存其他变量的地址的,因此指针本身也是有地址的,如果把指针的地址存到另一个指针变量中,那么就把这个指针变量叫作二级指针,而被存在这个指针变量中的指针叫做一级指针。
上面程序中,pa是一级指针,ppa就是一个二级指针,他保存的是pa的地址。
二、数组指针和指针数组
2.1 数组指针概述
int arr[4] = { 1,2,3,4 };
int(*parr)[4]=&arr;
*parr就是一个数组指针,他是一个指针,指向一个有4个元素,每个元素的类型是int的数组。
2.2 数组指针传参
数组指针的用途基本上都是作为函数的形参,用来接收实参传递过来的数组地址。
上面程序,传递的是二维数组的数组名即首行地址,首行地址即一维数组的地址。因此用一维数组的指针来接收。
2.3 指针数组概述
既然说到了数组指针,那么也提一下指针数组吧。
int arr1[3] = { 1,2,3 };
int arr2[3] = { 3,4,5 };
int arr3[3] = { 5,6,7 };
int* parr[3] = { arr1,arr2,arr3 };
指针数组的概念:指针数组是一个数组,里面存放的是指针。他跟数组指针写法很相似,不过他没有将*p给括起来,这就导致他是一个数组。因为[]的优先级要高于*号,因此parr先与[]结合成为一个数组,*号与int结合表示数组里的元素类型是int*。
表示parr数组中有3个元素,每个元素的类型是int*,即每个元素都是一个指针。所以叫指针 数组。
2.4 指针数组传参
可以看到形参是用二级指针来接收的,因为实参传递的是数组名,即parr的首元素地址(arr1的地址),arr1本身代表就是arr1首元素地址,因此他是一个指针,则实参parr传递的是指针的地址,因此需要二级指针来接收一级指针的地址。
三、字符指针
3.1 关键词const
const的作用是被const修饰的变量的值不可被修改。
上面程序中,const在*pa的左边,因此*pa不可被修改,但是pa可以被修改。
若const在*号右边、pa左边,则const修饰的是pa,这时候pa不可以被修改,但是*pa是可以被修改的。
3.2 字符指针概述
char* p = "hello world";
字符指针就是指针p指向了字符串“hello world”,p中保存的是首元素‘h'的地址,因此可以用p打印出整个字符串。字符指针的特点是所指向的字符串保存在代码区,在代码区的常量是不可被修改的。
因此char* p = "hello world"前面应该加上const -->const char* p = "hello world";这样一来可以更加直观的了解不能通过*p来修改"hello world"里面的内容。
四、函数指针
4.1 函数指针概述
int Add(int x, int y)
{
return x + y;
}
int main()
{
int(*pAdd)(int, int) = &Add;
return 0;
}
pAdd就是一个函数指针,他指向一个有2个形参,每个形参类型为int型,返回类型也是int类型函数。
4.2 函数指针的用法
首先函数名=&函数名,即函数名就是该函数的地址。因此pAdd=&Add=Add,平时我们调用函数时都是这么写的:函数名(实参),因此现在可以写成pAdd(实参),也有调用函数的作用。
4.3 函数指针数组
即数组里面的元素都是函数指针类型。
调用数组pf中的元素,可以间接的访问函数并使用该函数的功能。
结语:
如果本文对你起到了帮助,希望可以点赞👍+关注😎+收藏👌哦!如果有遗漏的地方欢迎大家在评论区补充~!!谢谢大家!!( ̄︶ ̄)↗