指针 即 指向某一个 变量 的内存地址
指针变量的定义
定义指针时,建议变量名为 p 开头
int a = 10, b = 20, *pa, *pb = &b;pa = &a; // 注意不是 *pa = &a此处 pa 为先声明后赋值,pb 为声明时赋值
声明后但未赋值的为野指针,禁止对其存取,因为其被随机指向了某一个内存空间
间接访问符
* 用来声明指针的同时,也是间接访问符
对于指针 int *p 和 int a = 6
令 p = &a
此刻 p 为 a 的内存地址,*p 则等同于 a,均为 6
指针与数组
指针变量+1 表示 跳过该指针变量对应的基类型所占字节数大小的空间
当指向数组时,其基类型为数组元素类型,指针变量+1表示跳过一个数组元素空间,指向下一个数组元素
数组名 a 相当于数组首元素 a[0] 的地址,即 a 等价于 &a[0]
例一:依次将输入的数据填入数组,并依次打印输出
int a[5], *p, i;p = a;cout << "请依次输入数组元素:" << endl;for (i = 0; i < 5; i++){ cin >> *p++;}cout << "数组的每个元素为:" << endl;for (p = a; p < a + 5; p++){ cout << *p << endl;}指针与二维数组
二维数组的存储结构为顺序形式,即二维数组中的数据元素在内存中的存储地址是连
访问数组元素的方法:
- 直接访问:a[i][j]
- 间接访问:((a+i)+j)
数组指针和指针数组
数组指针
数组指针,即指向一维数组的指针,是指向含 N 个元素的一维数组的指针
int (*p)[5];一维数组指针 p,该指针 p 只能指向含 5 个元素的整型数组
注:不要漏掉括号,下标运算符[] 比 *运算符 优先级高,p 首先与下标运算符 [] 相结合,说明 p 为数组,该数组中有 5 个元素,每个为 int * 型。即 p 为指针数组。
指向二维数组
int a[M][N];int (*p)[N]=a;两者变换关系
*(i 行首地址)=i 行首元素地址
0 行首地址:p + 0 <--> a + 01 行首地址:p + 1 <--> a + 1当定义一个指向一维数组的指针 p,并初始化为二维数组名 a 时,即 p=a,用该指针访问元素 a[i][j] 的两种形式 ((p + i) + j) 与 ((a + i) + j) 非常相似,仅把 a 替换成了 p 而已。
数组指针指向的是一整行,故数组指针每加 1 表示跳过一行
指针数组
即存储指针的数组,数组中的每个元素均是同类型的指针
int *a[5]指针数组最主要的用途是处理字符串,c语言中没有 字符串类型,定义字符串时常需要这样
char a[] = "sorry";或char a[] = {'s', 'o', 'r', 'r', 'y', '\0'}; // '\0'为字符串终止符,不使用会在sorry后打印乱码在 C 语言中,一个字符串常量代表返回该字符串首字符的地址(字符串其实就是字符数组,联想理解数组),即指向该字符串首字符的指针常量,因此根据上式子得。
char a[] = "sorry";char *p = a; // 此处 a 是指针,指向第一个字符 s 的地址,参考数组cout << a << endl;cout << p << endl;打印结果均为 sorry
由于指针数组的每个元素都是指针变量,因此,可以通过指针数组定义字符串数组:
char * c[4]={"if","else","for","while"};通过c[i]来获取每个字符串
指针与字符串
字符串指针常量
上节已知,字符串常量 “wdnmd” 为一个指针常量,指向第一个字符 w 的地址,打印字符串指针为从指针地址开始直到遇到’/0’,同理char a[] = "wdnmd",a 也是指针常量
类比数组的指针特性,可得:
char a[] = "abcd"cout << "abcd" + 1 << endl; // 打印bcdcout << a + 1 << endl; // 打印bcdcout << a + 2 << endl; // 打印cd注:‘/0’为字符串终止符,遇到即为字符串结束,详细见最后一节
既然字符串是个指针,那么可以通过间接访问的方式获取具体某一个字符
char a[] = "abcd"cout << *(a + 1) << endl; // 打印bcout << *(a + 4) << endl; // 打印空字符,为'/0'*(a + 5) // 已越界,禁止使用,其值不确定##¥¥ 字符串指针变量
通过字符指针变量可访问所指向的字符串常量,但仅限于读取操作
char *pc="abcd";pc="hello"; // 正确,修改pc指向,让其指向串"hello"*(pc+4) = 'p'; // 运行时错误。试图把'o'字符改变为'p'字符串变量
字符数组可以理解为若干个字符变量的集合,如果一个字符串存放在字符数组中,那么字符串中的每个字符都相当于变量,故可把存放在字符数组中的字符串称为变量字符串。
char str[10] = "wdnmd";定义字符数组并显示指定其大小(10),前六个空间分别为有效字符’w’ ‘d’ ‘n’ ‘m’ ‘d’ ‘\0’,第七个往后为’\0’填充
也可以不定义长度
char str[] = "wdnmd";自动为其分配6个空间,5个有效字符和结束符’/0’
允许使用数组下标方式改变数组中的元素,如
str[1] = 'r'; // 改为 "wrnmd"字符串结束符
上文已多次提到,不再赘述,注意几点:
- 定义确定长度的变量字符串时,长度一定要考虑到’/0’
- 逐个字符定义字符数组时,如
char a[] = {'a', 'b'},一定要手动在最后加一个’/0’,否则输出a为乱码甚至程序崩溃 - 定义
char a[3] = ""时,默认填充3个’/0’,此时手动给第2、3个元素赋值依然为空字符串,因为第1个元素为’/0’,自动终止
函数与指针
函数的两种调用方式
- 传值调用:传入的实参为固定值,函数内部将此值拷贝一份副本到形参变量,对副本进行操错,不会影响传入的数据,较大的数据时创建副本开销较大
- 传址调用:传入的实参为地址,形参为能接受地址的地址箱即指针变量,通过该地址间接访问要处理的数据,能在函数内改变函数外的数据,不涉及创建副本,开销较小
指针函数
即为返回类型为指针的函数,常用于字符串处理函数,格式
类型*函数名(形参列表){ ... /*函数体*/}函教指针
即指向函教的指针,C语言中,整型变量在内存中占一块内存空间,该空间的起始地址称为整型指针,可把整型指针保存到整型指针变量中。函数像其他变量一样,在内存中也占用一块连续的空间,把该空间的起始地址称为函数指针。而** 函数名就是该空间的首地址**,故函数名是常量指针。可把函数指针保存到函数指针变量中。
函数指针的定义
注意不要省略括号,省略为声明函数原型
返回类型(*指针变量名)(函数参数表);
int *pf (int, int);//声明了一个函数原型,函数名为pf,含两个int型参数,且该函数返回类型为整型指针类型,即int*。int (*pf) (int, int); //定义了一个函数指针变量pf,可以指向任意含有两个整型参数、且返回值为整型的函数。下面定义了一个函数:
int wdnmd(int a, int b){ ...}该函数符合 函数指针pf的条件,可以让pf指向此函数
pf=&func; //正确pf=func; //正确。也可省略&通过函数指针调用函数
如下,声明一个函数原型,定义函数指针并指向原型
int f(int a)int (*pf) (int) = &f当函数指针被初始化指向函数后,有三种调用函数方式
int result;result=f(2); //正确。编译器会把函数名转换成对应指针result=pf(2); //正确。直接使用函数指针result=(*pf)(2); //正确。先把函数指针转换成对应函数名函数调用时,编译器把函数名转换为对应指针形式,故前两种调用方式含义一样.而第三种调用方式,*pf 转换成对应的函数名 f(),编译时,编译器还会把函数名转换成对应指针形式,从这个角度来理解,第三种调用方式走了些弯路。
函数指针通常主要用于作为函数参数的情形。
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时