高级指针
指针即内存地址
> 程序有4G的虚拟地址
内存地址(虚拟内存): 4G
内存地址编号: 0—0xffffffff
编号的本质是一个整数
格式化输出地址 %p 看到的是一个十六进制的整数
指针只要有4个字节就能保存一个地址
指针变量:
保存了一个内存地址(的编号)的变量
空指针
NULL 0地址 stddef.h
---->> #define NULL ((void *)(0))
内存地址有类型之分
一个内存地址 只能存储8bit数据
多字节数据存储在多个地址上面,保存多字节数据的地址时只能保存首地址
*(内存地址) *指针变量 取内存地址中的数据
*取内存地址数据运算符
取到几个字节的数据取决于类型
数据类型 *指针变量;
数据类型* 指针变量的类型
空指针 悬空指针 NULL
野指针:
指向不确定的指针
万能指针:
void* 仅仅是用于保存地址 在使用时需要转换为特定的类型的指针
int *p1,p2;//p1是int*类型 p2是int类型
int *p1; int* p1; int * p1;//都可以 无所谓 保持一种风格即可
int *p1,*p2;//p1和p2都是 int* 类型
int n = 10;
int *p = &n;
int m = 0;
p = &m;
p = xx; //修改指针变量p指向 p变量本身的值
指针变量p有4个字节的内存空间 用于 保存另外一个内存地址的编号
*p == *(&m) = m
指针变量 加减 整数
指针变量+1 偏移了一个"单位"长度的字节数
int *p = &n;
p = p+1;
一维数组:
int arr[10] = {1,1,1};
arr[i] === (arr+i) === *(i+arr) ==== i[arr]
&arr[i] == &(arr+i) === arr+i
&arr[0] == &*(arr+0) === arr
一维数组名是第一个元素的地址
一维数组在传递过程中彻底变成了指针
//形参里的一维数组 其实是指针
void func(int arr[10]){ ==> void func(int arr[]) void func(int *arr)
sizeof(arr) === 4
//在函数里面不能用形参来求数组长度 所以才需要传递数组长度
}
int arr[10] = {0};
sizeof(arr) === 40
func(arr);
void func(int arr[],size_t len)
二级指针:
即指针变量的内存地址
int n = 10;
int *p = &n;
int **pp = &p;
pp == &p
*pp === *&p == p == &n
**pp === *p == n
修改普通变量的值:
n = 100; *p = 100; **pp = 100;
修改一级指针变量的值: 即修改一级指针指向
int m = 0;
p = &m; 等价 *pp = &m;
修改二级指针变量的值:
int *q = NULL;
pp = &q;
C语言中需要用到三级、四级指针解决的问题 只需要用二级指针就可以解决了
三级指针 四级指针
二维数组:
int arr[10];
arr == &arr[0] 数组中第一个元素的地址
&arr 一维数组的地址
arr + 1 : 加了一个数组中的元素的地址
&arr + 1: 加了一个数组的地址
int brr[4][10];
brr[0][0] 第一个元素的值
*(brr[0] + 0) == *brr[0] === *(*(brr+0) === **brr
brr[i][j] == *(brr[i] + j) == *(*(brr+i)+j)
&brr[0][0] == &(*(brr[0]+0]) == brr[0]
&(brr[0]) == &(*(brr+0) === brr
brr[0] ==== &brr[0][0] 第一个元素的首地址 int*
brr ==== &brr[0] 二维数组中第一个数组的地址
brr+i ==== &brr[i] 二维数组中第i个数组的地址
&brr ==== 二维数组的地址
二维数组名是一个一维数组的地址