C语言 第八章 指针(上)
第八章 指针(上)
地址和指针的基本概念
内容可变,地址不可变
有了变量的地址,存取变量就可以通过两种方式
- 通过变量名
- 通过变量的地址
1 | // 指针变量 |
基类型
指针变量所指向的变量的类型1
2
3
4
5
6
7
8
9
10
11
12
13
14int a = 1;
double b = 8.2;
int *p;
double *q;
void *r;
// p为int *型,只能指向int型
p = &a;
// q为double *型,只能指向double型
q = &b;
// r为void *型,可以指向任何类型
r = &a;
r = &b;
指针变量的赋值
指针变量值为0(地址值为0)时,表示什么也不指向 - 空指针。【地址值为NULL也表示空指针】
1 | int a = 1; |
赋值语句的方法1
p = &a;
定义指针变量时初始化(定义时赋初值)1
2int b = 2;
int *q = &b;
允许指针变量之间赋值,但另两个指针变量必须基类型相同1
2
3q = p;
int *r;
r = q;
特殊情况
1 | int *p; |
两运算符(&
, *
)
&
取地址运算符
获取变量的地址,用法:&变量名
*
指针运算符(间接访问运算符)
获取或改写以p为地址的内存内容
*p
,*
不是获得或改变指针变量本身的值,而是获得或改写它所指向单元的值。
int *p
,*
运算只能用于指针变量,不能用于普通变量(如*a
错误);
&
和*
互为逆运算
1 | int *p = &a; |
数组的指针
指针变量的运算
指向向前或向后移动n个单元,
p+n=p中的地址编号 + (每元素字节数*n)
p-n=p中的地址编号 - (每元素字节数*n)
概运算应只针对
指向数组的指针变量
进行,否则毫无意义
1 | int a[5] = {1,2,3,4,5}; |
每个
char
型变量占1个字节,对基类型为char
的指针变量+n,恰好是地址+n
1 | char c[4] = {'a', 'b', 'c', 'd'} |
void 类型的指针不能做+(-)n的运算(也不能++, –的运算)
指针的变量相减
两指针变量的加减乘除运算时没有意义的。
p1 - p2 = (p1中的地址编号 - p2中的地址编号)/镁元素字节数
关系运算
该运算一般只对指向同一数组的元素的两个指针变量进项,表示他们所指向元素的先后位置1
2
3
4
5
6
7
8// 表示p1和p2指向数组的同一个元素
p1 == p2
// 表示p1所指元素位于p2所指元素之后;
p1 > p2
// 表示p1所指元素位于p2所指元素之前;
p1 < p21
2
3
4
5
6
7
8
9// 与0和NULL比较
// 表示p为空指针
p == 0;
p == NULL;
// 表示p不是空指针
p != 0;
p != NULL;
数组元素的地址转换为元素下标
1 | int a[5] = {1,2,3,4,5}; |
两个重要公式
语法糖
编译时编译系统将
a[i]
全部变为*(a+i)
.
a[i]
就是语法糖,便于我们理解而设计的成为语法糖。
1 | int a[5] = {1,2,3,4,5}; |
指针变量可写为数组的形式
1 | int *p = x[0]; |
指针变量与一位数组名的统一
1 | int a[5]; |
指针运算的优先级
&
, *
的优先级和++
, --
相同,都非常高,仅次于()
与++
, --
统计运算时,从右至左结合
二维数组的指针
1 | // 行指针 |
一个表格、两句法则
草稿写法 | ±1效果 | 定义 | |
---|---|---|---|
二级指针 | [[]] | 移动一行 | int (*q)[4]; int b[3][4]; 中的b |
二级指针 | [[]] | 必移动4字节 | int **r; int *s[3]; 中的s |
一级指针 | [] | 移动一个单位(int型4字节,char型1字节…) | int *p; int a[2]; 中的a |
普通变量 | 变量值±1 | int x; |
法则:
- 定义变量时:一个
*
或一个[]
升一级 - 使用时:一个
*
或一个[]
降一级;一个&
升一级
两个重要公式
二维数组元素的写法
a[i][j]
是*(*(a+i)+j)
的语法糖
1 | x[i] == *(x+i); |