指针
一、指针的重要性
- 表示一些复杂的数据结构
- 快速的传递数据,减少了内存的消耗
- 使函数返回一个以上的值
- 能直接访问硬件
- 能够方便的处理字符串
- 是理解面向对象语言中引用的基础
- 指针是C语言的灵魂
二、指针的定义
1. 地址
- 内存单元的编号
- 从0开始的非负整数
2. 指针
- 指针就是地址,地址就是指针
- 指针变量就是存放内存单元编号的变量,或者说指针变量就是存放地址的变量
- 指针和指针变量的两个不同的概念
- 通常我们叙述时会把指针变量简称为指针,实际它们含义并不一样
- 指针的本质就是一个操作受限的非负整数
三、指针的分类
1. 基本类型指针
| #include <stdio.h>
int main(int argc, char const *argv[])
{
int *p;
int i = 3;
p = &i;
printf("%p\n", p); // 0x7ffff3688088
return 0;
}
|
1. 指针的理解
-
p
是变量的名字,int *
表示p变量存放的是int类型变量的地址
-
int *p;
不表示定义了一个名字叫做*p
的变量
- 应该这样理解:
p
是变量名,p
变量的数据类型是int *
类型,所谓int *
类型,实际就是存放int
变量地址的类型
- p保存了i的地址,因此p指向i
- p不是i,i也不是p,更准确的说:修改p的值不影响i的值,修改i的值也不会影响p的值
- 如果一个指针变量指向了某个普通变量,则
*指针变量
就完全等同于普通变量
,例如此处*p
就完全等同于i
*
的含义:
- 乘法
- 定义指针变量
- 指针运算符,该运算符放在已经定义好的指针变量前面,如果p是一个已经定义好的指针变量,则
*p
表示以p的内容为地址的变量。
2. 指针常见错误
错误1:
| #include <stdio.h>
int main(int argc, char const *argv[])
{
int *p;
int i = 5;
*p = i;
printf("%d\n", *p);
return 0;
}
// 运行错误Segmentation fault (core dumped)
|
错误2:
| #include <stdio.h>
int main(int argc, char const *argv[])
{
int *p;
int *q;
int i = 5;
p = &i;
*q = p; // 语法错误
printf("%d\n", *q);
return 0;
}
|
3. 指针变量的运算
- 指针变量不能相加、不能相乘、不能相除
- 如果两个指针变量指向的是同一块连续空间中的不同存储单元,则这两个指针变量才可以相减。
4. 指针经典程序-互换两个数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | #include <stdio.h>
void swap(int *p, int *q)
{
int t;
t = *p;
*p = *q;
*q = t;
}
int main(int argc, char const *argv[])
{
int a = 3;
int b = 5;
swap(&a, &b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
|
2. 指针和数组
2.1 指针和一维数组
1. 指针和数组名
一维数组名是个指针常量,它存放的是一维数组第一个元素的地址
2. 指针和下标
如果p是个指针变量,则p[i]
永远等价于*(p+i)
3. 函数处理数组
如果函数要处理一个一维数组,则需要接收该数组的2个信息:
- 数组第一个元素的地址
- 数组的长度
3. 指针和函数
4. 指针和结构体
5. 多级指针
| int i = 10;
int *p = &i; // p只能存放int类型变量的地址
int **q = &p; // q是int **类型,p只能存放int *类型变量的地址
int ***r = &q; // r是int ***类型,r只能存放int **类型变量的地址
|