五、指针
指针的优点
1)使程序更简洁、紧凑、高效
2)有效的表达更复杂的数据结构
3)动态分配内存
4)得到多余一个数的函数返回值
1、概念
地址:内存中每一个字节单位都有的一个编号
指针:指针就是地址
指针变量:用于存放地址的变量就叫指针变量
2、格式
存储类型 数据类型* 指针变量名;
示例
int num = 5;
int *p = #
char ch = 'a';
char *q = &ch;
3、指针操作符
&:取地址符,获取变量的地址
*:取内容,获取地址里面的内容
int a = 10;
*&a == a; // *和&都是单目运算符,互逆运算
*(&a) // a是变量,先取地址,然后通过地址取内容
&*a // 是错的,&(*a) a是变量,不能取内容
int *b = &a
&*b == b // b是地址,先取内容,然后取该内容的地址
4、初始化
指针变量在使用前不仅要定义还要初始化,位初始化的指针变量不能随便使用,会产生野指针
1、将变量的地址赋值给指针变量
1)int *p = &a; // 定义的同时赋值
2)int *p = NULL;
p = &a; // 先定义后赋值
*p = 5; // 可以通过*p改变指向的内容
2、将数组的首地址赋值给指针变量
char s[10] = "hello"; // 相当于指向了第一个元素
char *p = s; // 数组指向数组首地址,即指向‘h'的地址
3、将指针变量里面保存的地址赋值给另一个指针变量
int a = 10, b;
b = a;
int *p = &a;
int *q = p;
5、指针运算
1、算数运算
char s[32] = "hello";
char *p = s;
p++; // 指针指向高地址方向移动一个数据单位,指针指向发生变化
p--; // 指针向低地址方向移动一个数据单位,指针指向发生变化
示例:
int *p = &a;
p++; // 移动4个字节
double *q = &b;
q++; // 移动8个字节
#include <stdio,h> int main(int argc, char const *argv[]) { char s[10] = "hello"; char *p = s; printf("%p %p\n", &s[0], &s[1]); p++; printf("%p\n", p); printf("%c %c\n", *p, *s); printf("%s %s\n", p, s); return 0; }
p+n:向高地址方向访问第n个数据的地址,指针指向不发生变化
p-n:向低地址方向访问第n个数据的地址,指针指向不发生变化
偏移了多少地址(字节) = n * sizeof(数据类型)
两个地址之间的差 == 两个地址之间相隔的元素个数
q - p = 之间相隔的元素个数
int m = 100; double n =200; int *p1 = &m; int *p2 = p1 + 2; double *q1 = &n; double *q2 = q1 + 2; printf("p1=%p p2=%p\n", p1, p2); printf("p2-p1=%d\n", p2-p1); printf("q1=%p q2=%p\n", q1, q2); printf("q2-q1=%d\n", q2-q1);
2、关系运算
< > == !=
指针之间的关系运算比较的是它指向的地址的高低
指向高地址的指针大于指向低地址的指针
char s[32] = "hello"
char *p1 = &s[1];
char *p2 = &s[3];
p2 > p1;
注意:指向不同类型数组的指针进行关系运算时没有意义,
指向不同区域的指针关系运算也没有意义
(同一个数组之间进行比较)