文章目录
前言
一、指针的基本用法
1.指针的作用
2.地址和变量
3.指针
二、指针运算
算数运算
关系运算
三、指针与数组
三、指针与多维数组
行地址(数组指针)
五、字符指针和字符串
六、指针数组
七、多级指针
八、void指针和const修饰符
void指针
const修饰符
写在最后
一、指针的基本用法
1.指针的作用
使程序简洁、紧凑、高效
有效地表示复杂的数据结构
动态分配内存
得到多于一个的函数返回值
2.地址和变量
在计算机内存中,每一个字节单元,都有一个编号,称为地址
注:1Byte = 8 Bit
在C语言中,内存单元的地址称为指针,专门用来存放地址的变量,称为指针变量
在不影响理解的情况中,有时对地址、指针和指针变量不区分,通称指针
3.指针
一般形式如下:
<存储类型> <数据类型> * <指针变量名> ;
举个例子:(auto) char *pName;
注意:指针指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型。简称为指针的数据类型
指针在说明的同时, 也可以被赋予初值,称为指针的初始化
<存储类型> <数据类型> *<指针变量名> = <地址量> ;
举个例子:(auto) int a, *p=&a;
上面的过程类似于下图的关系
指针指向的内存区域中的数据称为指针的目标
如果它指向的区域是程序中的一个变量的内存空间, 则这个变量称为指针的目标变量。 简称为指针的目标。我们可以使用*来获得对应目标的值
设px为一个指针,则:
px — 指针变量, 它的内容是地址量
*px — 指针所指向的对象, 它的内容是数据
&px — 指针变量占用的存储区域的地址,是个常量
每个指针变量都有一个数据类型,只有数据类型相同的才可以互相赋值,否则不可以(程序的行为将不可预料)!
float a, *px, *py; px = &a; py = px;
二、指针运算
算数运算
关系运算
注:常用但是p!=NULL其中NULL表示空指针,一般表示指针是空。是特殊的一个标记。
三、指针与数组
在C语言中,数组的指针是指数组在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址 。
设指针变量px的地址值等于数组指针x(即指针变量px指向数组的首元数),则:
x[i] 、*(px+i)、*(x+i)和px[i]具有完全相同的功能:访问数组第i+1个数组元素
注意:
指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同的形式,因为指针变量和数组名都是地址量
但指针变量和数组的指针(或叫数组名)在本质上不同,指针变量是地址变量,而数组的指针是地址常量
举个例子
int a[] = {1,2,3,4,5,6}, *p = a,i ;
p++,p--(对)
a++,a--(错),因为数组名是一个常量不能做运算。
a+1,*(a+2)(对)
三、指针与多维数组
可把二维数组看作由多个一维数组组成。
二维数组名代表数组的起始地址,数组名加1,是移动一行元素。因此,二维数组名常被称为行地址
行地址(数组指针)
存储行地址的指针变量,叫做行指针变量。形式如下:
<存储类型> <数据类型> (*<指针变量名>)[表达式] ;
例如int a[2][3]; int (*p)[3];
方括号中的常量表达式表示指针加1,移动几个数据。(也就是一行)
当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。
注意:p是一级指针,每次移动3个元素,并不是二级指针!!!
五、字符指针和字符串
我们把char数据类型的指针变量称为字符指针变量。
初始化字符指针是把内存中字符串的首地址赋予指针,并不是把该字符串复制到指针中。
char str[] = “Hello World”; char *p = str;
错误举例:
char * p = “Hello World”; *p = ’h‘; // 错误, 字符串常量不能修改
六、指针数组
指由若干个具有相同存储类型和数据类型的指针变量构成的集合
指针数组的一般说明形式:
<存储类型> <数据类型> *<指针数组名>[<大小>];
指针数组名表示该指针数组的起始地址。
举个例子:
double * pa[2]
注意:与double (*p)[2]的区别。一个是数组,一个是一级指针的类型。
就是后面的元素对应关系为*pb[0]--->b[0][0]、*pb[1]--->b[0][1]、*pb[2]--->b[0][2]。
原因是[]优先级高于*所以是先进行取对应数组元素 在对相应的值解引用!
七、多级指针
一个指向指针变量的指针变量,称为多级指针变量
对于指向处理数据的指针变量称为一级指针变量,简称一级指针
而把指向一级指针变量的指针变量称为二级指针变量,简称二级指针
二级指针变量的说明形式如下
<存储类型> <数据类型> ** <指针名> ;
其实高级指针就是告诉程序这是一个多少级的间接索引。比如二级指针就是需要进行两次查找值才是最终的数据。三级指针就是需要进行三次取值才是最终的数据。
八、void指针和const修饰符
void指针
void指针是一种不确定数据类型的指针变量,它可以通过强制类型转换让该变量指向任何数据类型的变量
一般形式为: void * <指针变量名称> ;
注意:对于void指针,在没有强制类型转换之前,不能进行任何指针的算术运算
const修饰符
1.常量化变量的值
一般说明形式如下: const <数据类型> 变量名 = [<表达式>] ;
常量化变量是为了使得变量的值不能修改
2.常量化指针目标表达式
一般说明形式如下: const <数据类型> * <指针变量名称>[= <指针运算表达式>] ;
常量化指针目标是限制通过指针改变其目标的数值 ,但<指针变量>存储的地址值可以修改
int a; const int *p; p = &a; (*p)++;(报错)
限制我们通过指针改值
3.常量化指针变量
一般说明形式如下: <数据类型> * const <指针变量名称>[= <指针运算表达式>] ;
使得<指针变量>存储的地址值不能修改。但可以通过 *<指针变量名称> 可以修改指针所指向变量的数值
int a; int * const p; p = &a;(报错)
限制我们改地址
4.常量化指针变量及其目标表达式
一般说明形式如下:
const <数据类型> * const <指针变量名> = <指针运算表达式> ;
常量化指针变量及其目标表达式,使得既不可以修改<指针变量>的地址,也不可以通过*<指针变量名称>修改指针所指向变量的值
int a; const int * const p = &a; p = &a;(报错) (*p) = 0;
限制我们改地址和通过地址改值
总结:
1.const修饰谁谁就不能改。
2.面试问到我们可以说const一般代表只读。
举个例子:上面的const int *p修饰的是*p所以*p不能改,而int * const p那么p就是不能改的。