1. 指针
指针就是存储的变量的地址,指针变量就是指针的变量。
1.1 空指针
当定义一个指针没有明确指向内容时,就可以将他设置为空指针
int* p = NULL;
这样对空指针的操作就会使程序崩溃而不会导致出现未定义行为,因为程序崩溃是宏观的,被察觉的,未定义行为是不被察觉的。
所以在操作一个不明确指针的时候,最好对它进行判空处理。
if (p == NULL){
//为空的处理
}
1.2 野指针
只要指针指向的内存区域是未知的,那么该指针就是野指针。
因为指向的内存区域未知,那么操作该指针就会导致未定义行为
1.3 指针的传参
C语言函数的传参都是值传递的
这意味着当调用函数时,传递给函数的是实际参数的副本,而不是参数本身。因此,函数内部对参数的修改不会影响外部的实际参数。
那为什么指针作为参数传递时就会直接改变其指向的内容呢?
那是因为指针作为实参传递给函数的形参,这个形参是实参的拷贝,但是实参的形参都指向的是同一个地址空间。 相当于:
int a = 10;
int* p1 = &a;
int* p2 = &a;
p1和p2是两个不同的指针变量,但存储的内容是一样的。
即对指向那片内存空间的指针做出解引用改变的操作就会发生数值的改变。
void swap(int* a, int* b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
void swap_ptr(int* a, int* b) {
int* tmp = a;
a = b;
b = tmp;
}
void swap_ptr_pro(int** pa, int** pb) {
int* tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main() {
int a = 10, b = 20;
swap(&a, &b);//改变
printf("%d %d\n", a, b);
int* pa = &a, * pb = &b;
swap_ptr(pa, pb);//不改变
printf("%d %d\n", *pa, *pb);
a = 10, b = 20;
swap_ptr_pro(&pa, &pb);//改变
printf("%d %d\n", *pa, *pb);
printf("%d %d", a, b);
return 0;
}
上述代码swap函数就可以交换a和b的值,但是swap_ptr就不行,因为它交换的指针变量,而不是指向的值,交换指针变量是不会有结果的,因为他只是拷贝。
第三个函数swap_ptr_pro更是重量级,我在第二个函数中想通过交换两个指针变量来实现数值的交换,相当于
int* pa = a;
int* pb = b;
//转化为
int* pa = b;
int* pb = a;
这样直接printf(“%d %d\n”, *pa, *pb);就可以交换两个值,但是第二个函数交换的只是拷贝,不能实现,所以第三个函数我直接传二级指针,直接对一级指针pa,pb做修改。*pa就相当于pa的地址,这次我的形参是int ** a, int ** b.和&pa,&pb指向的是同一块内存,所以可以直接修改pa和pb,以实现交换 *pa和 *pb的值。
但是
printf("%d %d\n", *pa, *pb);
printf("%d %d", a, b);
这两句运行出来结果不一样,为啥?
这是因为我只交换了*pa和 *pb的值,而不是a和b的值。
交换a,b的值需要pa和pb
交换 *pa和 *pb的值需要&pa,&pb。
2.数组名于指针的关系
数组名可以看作是不可改变指向的指针,数组名可以看作是指向首元素的指针
只有两种情况下数组名才不代表首元素地址:
1:sizeof(arr) 这种情况下计算的是数组一共占用多少字节
2:&arr 和 arr相区别,arr代表的是数组的首元素地址,&arr代表数组的地址
2.1 数组指针和指针数组
数组指针:本质是一个指针,是一个指向数组变量的指针
int arr[4];
int(*p)[4] = &arr;
指针数组:本质是一个数组,是一个存储指针变量的数组,即数组存储的元素是指针变量
int* p[3] = {&a, &b, &c};
2.2常量指针和指针常量
int main() {
int a = 10;
const int* p1 = &a;
int* const p2 = &a;
int const* p3 = &a;
return 0;
}
const int * p1 = &a;
- 含义:p1 是一个指向 const int 的指针。
- 解释:p1 指向的值是 const 的,即不能通过 p1 修改它所指向的值。
int * const p2 = &a;
- 含义:p2 是一个指向 int 的常量指针。
- 解释:p2 本身是 const 的,即不能修改 p2 指向的地址,但可以通过 p2 修改它所指向的值。
int const * p3 = &a;
- 含义:p3 是一个指向 const int 的指针。
- 解释:p3 指向的值是 const 的,即不能通过 p3 修改它所指向的值。
const右边是只有指针变量,就限制的是这个指针变量,即这个指针变量不能再指向其他的值
const右边还有int或者,那么限制的就是指针变量指向的值,即指针指向的值不能修改