char型指针
char型指针实际上跟别的类型的指针并无本质区别,但是由于C语言中的字符串以字符数组的方式存储,而数组在大多数场合又会表现为指针,因此字符串在绝大多数场合就表现为char型指针。
- 定义:
char * = "abcd";
多级指针
- 如果一个指针变量p1存储的地址,是另一个普通变量a的地址,那么称p1为一级指针
- 如果一个指针变量p2存储的地址,是指针变量p1的地址,那么称p2为二级指针
- 如果一个指针变量 p3 存储的地址,是指针变量 p2 的地址,那么称 p3 为三级指针
- 以此类推,p2、p3等指针被称为多级指针
- 示例:
int a = 100;
int *p1 = &a; // 一级指针,指向普通变量
int **p2 = &p1; // 二级指针,指向一级指针
int ***p3 = &p2; // 三级指针,指向二级指针
指针万能拆解法
- 任意的指针,不管有多复杂,其定义都是由两部分组成
- 第一部分:指针所指向的数据类型,可以是任意类的类型
- 第二部分:指针的名字
- 示例:
char (*p1); // 第2部分:*p1; 第1部分:char;
char *(*p2); // 第2部分:*p2; 第1部分:char *;
char **(*p3); // 第2部分:*p3; 第1部分:char **;
char (*p4)[3]; // 第2部分:*p4; 第1部分:char [3];
char (*p5)(int, float); // 第2部分:*p5; 第1部分:char (int, float);
- 注解:
- 上述示例中,p1、p2、p3、p4、p5本质上并无区别,它们均是指针
- 上述示例中,p1、p2、p3、p4、p5唯一的不同,是它们所指向的数据类型不同
- 第1部分的声明语句,如果由多个单词组成,C语言规定需要将其拆散写到第2部分的两边
void型指针
- 概念:无法明确指针所指向的数据类型时,可以将指针定义为 void 型指针
- 要点:
- void 型指针无法直接索引目标,必须将其转换为一种具体类型的指针方可索引目标
- void 型指针无法进行加减法运算
- void关键字的三个作用:
- 修饰指针,表示指针指向一个类型未知的数据。
- 修饰函数参数列表,表示函数不接收任何参数。(预习)int main(void)
- 修饰函数返回类型,表示函数不返回任何数据。(预习)void func(int)
- 示例:
// 指针 p 指向一块 4 字节的内存,且这4字节数据类型未确定
void *p = malloc(4);
// 1,将这 4 字节内存用来存储 int 型数据
*(int *)p = 100;
printf("%d\n", *(int *)p);
// 2,将这 4 字节内存用来存储 float 型数据
*(float *)p = 3.14;
printf("%f\n", *(float *)p);
// a 为不确定类型
//void a = 10;
int data = 10;
// 定义通用类型指针p指向data的地址,但是p的类型不确定
void *p = &data;
// 输出的时候要确定p的类型,所以需要强制类型转换,否则报错
printf("%d\n",*(int *)p);
void类型总结:
void 一般运用在指针或者,函数的返回值,或者函数的参数传递,不能用在非指针的定义,比如 void a = 10;错误
作业:
1.复习今天的内容,并且自行敲一遍或多遍代码直到掌握为止
2. 完成字符串逆序输出
3. 预习const类型指针
const 型指针
- const型指针有两种形式:①常指针 ②常目标指针
- 常指针:const修饰指针本身,表示指针变量本身无法修改。
char* const p;
- 常目标指针:const修饰指针的目标,表示无法通过该指针修改其目标。
const int *p;
int const *p;
- 常指针在实际应用中不常见。
- 常目标指针在实际应用中广泛可见,用来限制指针的读写权限
- 示例:
int a = 100;
int b = 200;
// 第1中形式,const修饰p1本身,导致p1本身无法修改
int * const p1 = &a;
// 第2中形式,const修饰p2的目标,导致无法通过p2修改a
int const *p2 = &a;
const int *p2 = &a;
函数指针(函数)这里先提一下这个
- 概念:指向函数的指针,称为函数指针。
- 特点:函数指针跟普通指针本质上并无区别,只是在取址和索引时,取址符和星号均可省略
- 示例:
void f (int); // 函数 f 的类型是: void (int)
void (*p)(int); // 指针 p 专门用于指向类型为 void (int) 的函数
p = &f; // p 指向 f(取址符&可以省略)
p = f; // p 指向 f
// 以下三个式子是等价的:
f (666); // 直接调用函数 f
(*p)(666); // 通过索引指针 p 的目标,间接调用函数 f
p (666); // 函数指针在索引其目标时,星号可以省略
-
要点:
- 函数指针是一类专门用来指向某种类型函数的指针。
- 函数的类型不同,所需要的函数指针也不同。
- 函数的类型,与普通变量的类型判定一致,即去除声明语句中的标识符之后所剩的语句。
-
问:一维数组会被视为一级指针,那二维数组是不是等价于二级指针?
-
答:
这种说法是错误的,不能这么简单的类推,实际上,二维数组与二级指针没有任何必然关系。
任何数组a,除了定义语句和sizeof表达式之外,都会被一律视为一个指向其首元素的指针,因此,除非该数组的元素类型本身恰好是指针,即一维指针数组在运算时会被视为二级指针,但题目中提到的二维数组,其元素显然应该是一维数组,因此二维数组在运算时会被视为指向数组的指针,即数组指针。
例如:
int a[3];
// 此处的a等价于 &a[0],而a[0]是一个int,因此此处a的类型是 int (*)
int *p = a+1;
int a[2][3];
// 此处的a等价于 &a[0],而a[0]是一个int[3],因此此处a的类型是 int (*)[3]
int (*p)[3] = a+1;
int *a[3];
// 此处的a等价于 &a[0],而a[0]是一个int *,因此此处a的类型是 int (*)*
int **p = a+1;