【笔记】指针
c++ 一本通上在第一章就有指针讲解,但是当时老师跟我们说学这个东西没用,还会误导人,所以就直接略了过去 。
直到现在,在我 qbxt 七日游中,STL 中的 set 成功让我认识到了指针的重要性(不会没法用 set),因此特地在网上恶补一番,顺便做个笔记 。
定义指针类型
int *a = &b // 定义一个 int 类型的指针 a 并指向 int 类型的变量 b
double *a = &b // 定义一个 double 类型的指针 a 并指向 double 类型的变量 b
Node *a = &b // 定义一个名称为 Node 的结构体类型的指针 a 并指向名称为 Node 的结构体类型的变量 b
int **a = &b // 定义一个 int 类型的指针 a 并指向 int 类型的指针 b
int (*a)[5] = &b // 定义一个有 5 个 int 类型的数组指针 a 并指向一个有 5 个 int 类型的数组 b
int *a = b // 定义一个 int 类型的指针 a 并指向一个名称为 b 的 int 类型的数组的第一个元素
int (*a)(int, int) = b // 定义一个返回类型为 int,有 2 个 int 形参的函数指针并指向函数 b(b 前可以加 &)
const char *a = "LKP AK IOI" // 定义一个 char 类型的常量指针 a 并指向一个元素为 "LKP AK IOI" 的字符数组
-
赋值号必须加(一定要赋值,不然会形成野指针导致程序出错)。
-
用取地址或者
NULL
来赋值 。 -
总之必须赋值
调用指针对象及修改
int b = 64;
int *a = &b;
printf("%d\n", *a);
printf("%d\n", b);
*a = 32;
printf("%d\n", *a);
printf("%d\n", b);
结果:
struct Node {
int l, r;
double tmp;
char id[8];
};
Node b = (Node){1, 5, 62.4, "114514"};
Node *a = &b;
printf("%d %d %lf %s\n", a -> l, a -> r, a -> tmp, a -> id);
printf("%d %d %lf %s\n", b.l, b.r, b.tmp, b.id);
a -> l = 4;
a -> tmp = 23.3;
printf("%d %d %lf %s\n", a -> l, a -> r, a -> tmp, a -> id);
printf("%d %d %lf %s\n", b.l, b.r, b.tmp, b.id);
结果:
-
指针中可以通过修改指针(需加上
*
,不加会 CE(不能修改地址))来修改原变量值 。 -
输出指针时加上
*
会输出指针所指变量值 。 -
输出指针时不加上
*
会输出指针所指变量地址 。
指针之间的赋值
直接赋值就行 。
int b = 64;
int *a = &b;
int *c = a;
printf("%d\n", *a);
printf("%d\n", b);
printf("%d\n", *c);
结果:
-
定义的指针变量如果加
*
则整体为该指针所指的变量值 。 -
定义的指针变量如果不加
*
则整体为该指针所指的变量地址 。 -
取指针的地址直接用
&
,不要再加上*
。 -
用 1 号指针给 2 号指针赋值时,1 号指针不要加上
*
。
指针的隐藏要素
-
用指针去指向数组变量时,以及指向其他类型变量时,要使指针类型与被指向元素类型一致,不然会出问题(尽量不用强制转换) 。
-
强制转换方法:
*(char*)a
,将指针 \(a\) 转换为 char 类型 。
注意:强制转换时,指针本身的 *
要在强制类型前,强制类型后要加上 *
以示为指针 。
指针的加减
指针只能与常量进行加减,且与正常加减意义不同 。
通常指针的加减是在数组指针中进行的 。
int b[10] = {0, 1, 2, 3, 4, 5};
int *a = b;
printf("%d\n", *a);
printf("%d\n", *a + 1);
printf("%d\n", *a + 2);
printf("%d\n", *a + 3);
printf("%d\n", *a + 4);
结果:
-
指针可以自增自减 。
-
指针加减的常数可以看做是数组中的位置 。
-
直接输出数组名会返回数组第一个元素的地址 。
-
直接输出数组名加某常数会返回从数组第一个元素开始第
sizeof(元素类型) * 该常数
。
函数中的指针
传参
void swap(int *a, int *b) {
*a ^= *b ^= *a ^= *b;
}
int a = 96, b = 64;
swap(&a, &b);
printf("%d %d\n", a, b);
结果:
用指针指向函数
int add(int a, int b) {
return a + b;
}
int (*c)(int,int) = add; // add 前加不加 & 都一样
int a = c(1,2); // 可以当做函数名,c 前加不加 * 都一样
常量指针
指针本身是常量
int a = 97, b = 98;
int* const c = &a;
*c = 98; // 改变了指针所指向的变量的值,正确
c = &b; // 改变指针所指地址,错误
指针指向常量
int a = 97, b = 98;
const int* c = &a; // 或写成 int const *c = &a;
c = &b; // 改变了指针所指地址,正确
*c = 98; // 改变指针所指常量的值,错误