亲爱的友友们,不知你们是否理解c语言的指针呢?
如果并不了解,或是有些许困惑,不妨来看看这篇文章吧,希望你能从中有所启发(手动比心)
目录
1.初识指针
1.1 举例——交换两数值
1.2 指针的相关符号 —— * ,&
1.3指针+-整数
1.4 const修饰指针变量
1.5 野指针
2.数组与指针
2.1数组名
2.2一维数组传参
3.二级指针
4.指针数组
5.数组指针
6.函数指针
7.函数指针数组
1.初识指针
1.1 举例——交换两数值
首先让我们来看一个程序——用函数实现交换a,b的值,这道题对于你们来说应该很简单,但是如果不熟悉指针的人可能会写出下面的代码:
#include void swap(int x, int y); int main() { int a = 1; int b = 2; swap(a, b); printf("a=%d\n", a); printf("b=%d\n", b); return 0; } void swap(int x, int y) { int t = x; x = y; y = t; }
乍一看好像没什么问题是吧?但是将程序运行起来,我们将会得到以下结果 :
可以看到,a,b的值并没有实现交换,所以为什么没有写成函数时一切正常,但是一使用函数就没办法交换了呢?
其实是因为函数在被调用的时候,形参是被临时创建的,一旦出了函数,它们就会被销毁。运行函数时将a,b的值赋给了x,y,实现了x,y的值的交换,然后函数调用结束,x,y就死了,本质上并没有对a,b造成任何影响。
由此可见,我们急需一个东西使得函数能够与实参建立联系,于是c语言就引入了指针,指针可以访问到想要访问的变量的地址,从而敲开变量家的门,交换两个变量家里的人。(是不是有点像高位者对低位者行使权力,形参和实参等级相同,都是int类型,所以无法通过该形参去改变实参)通过指针,我们就可以通过函数改变实参的值,所以将交换两数的值的代码进行改造:
#include void swap(int* x, int* y); // int main() { int a = 1; int b = 2; swap(&a, &b); // printf("a=%d\n", a); printf("b=%d\n", b); return 0; } void swap(int* x, int* y) // { int t = *x; // *x = *y; // *y = t; // }
结果就可以正确了 。
我将所有有变化的地方都用//进行标出,就会发现两个新的符号——“ * ”,“ & ”。
1.2 指针的相关符号 —— * ,&
取地址操作符(&)
在C语⾔中创建变量其实就是向内存申请空间,内存里面的每一个空间都有它们自己的地址,就像每一个人的家都有独一无二的坐标一样,家就是内存空间,而坐标就是地址,一个变量住进一个家,也就有了一个地址,而“&”(取地址操作符)就是可以获取变量地址的操作符。
例如:&a就获得了a的地址
地址表示
32位机器有32根地址总线(还有64位机器,这里以32位平台举例),每根线只有两态,表⽰0,1(电脉冲的有⽆),那么⼀根线,就能表⽰2种含义,2根线就能表⽰ 2x2=4 种含义,依次类推。32根地址线,就能表⽰2^32种含义,每一种含义就代表着一个地址,
我们知道,一个字节有8个比特位,所以存储一个地址就需要用32/8=4个字节(也就是一个指针的大小,因为指针存放的就是变量的地址)。
解引用操作符(*)
其实操作符“ * ”有两个用途:
1.定义一个指针变量
int a;是定义了一个整型的变量a。
int* b;就是定义了一个指向整型变量的指针。
b=&a;b就得到了a的地址
有多少不同类型的变量,就可以有对应不同类型的指针。char* a,double* a 等等。但是指针的类型必须和变量类型一一对应!因为不同类型的指针访问的权限不同,char*类型的指针解引用(就是下面的第二个用途)后只能访问char类型对应的一个字节,int*类型也是一样。
2.获取指针所指向变量的值(解引用)
int a=5;//定义变量a int* p=&a;//p得到a的地址 *p=10;//通过解引用改变a的值
p得到a家的地址还不够,想要改变a的值就要通过“ * ”来进入a的家来改变a的值。
1.3指针+-整数
指针+-整数代表着指针指向位置的移动,移动的多少与指针类型有关(这也是指针类型与变量类型要一一对应的原因),char*类型指针+1代表跳过内存中的一个字节,指向下一个字节的地址,int*类型就是四个字节
要注意,在指针类型中有⼀种特殊的类型是 void* 类型的,可以理解为无具体类型的指针(或者叫泛型指针),这种类型的指针可以用来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进行指针的+-整数和解引用的运算,因为不知道要跳过几个字节。
1.4 const修饰指针变量
我们知道变量是可以修改的,如果把变量的地址交给⼀个指针变量,通过指针变量的也可以修改这个变量,但是一旦这个指针变量用const修饰了(如:const char* p)编译器就不允许改变该指针存放的地址里面的值了!
1.5 野指针
所谓野指针就是没有明确指向的指针,它的成因有以下几种 :
1.指针未初始化
int main() { int *p;//局部变量指针未初始化,默认为随机值 *p = 20; return 0; }
2.指针越界访问
int main() { int arr[10] = {0}; *p = &arr[0]; int i = 0; for(i=0; i{1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7}}; test(arr, 3, 5); return 0; }
还没有评论,来说两句吧...