<C++>4 指针和结构体
本文最后更新于:2022年6月19日 晚上
4 指针和结构体
4.1 指针
指针的作用:可以通过指针间接访问内存
- 内存编号是从 0 开始记录的。一般用十六进制数字表示
- 可以用指针变量保存地址
4.1.1 指针的定义和使用
语法:
- 声明指针:
数据类型 * 指针变量名
- 记录地址:
指针变量名 = &变量名
- 使用指针:
*指针变量名
int var = 10; //这是某个变量
int * p; //声明了指针 p
p = &var; //让 p 记录 var 的地址。& 是一个取址符
*p = 5; //*p 即通过 p 的地址找到其引用的变量
//这个场合,var 的数值改变了
指针所占内存空间:
-
32 位操作系统(x86):4 字节(任何类型)
-
64 位操作系统(x64):8 字节(任何类型)
4.1.2 空指针和野指针
空指针:指针变量指向内存中编号为 0 的空间。空指针指向的内存不能被访问。
可以用空指针初始化指针变量。
char * p;
char a = 'a';
p = &a;
p = NULL; //此时 p 成为空指针
野指针:指针变量指向非法的内存空间
4.1.3 const 修饰指针
const 修饰指针有三种情况:
-
const 修饰指针(常量指针):
const 数据类型 * 指针名
常量指针:指针的 指向 可以修改,但指针 指向的值 不能修改
double d = 1.5; const double * dp = &d; //常量指针 double d2 = 3.5; dp = &d2; //指针的指向可以修改 /*dp = 2.5; 这个不行*/ //指针指向的值不能修改
-
const 修饰常量(指针常量):
数据类型 * const 指针名
指针常量:指针 指向的值 可以修改,但指针的 指向 不能修改
int i = 10; int * const ip = &i; //指针常量 *ip = 15; //指针指向的值可以修改 int n = 25; /*ip = &n; 这个不行*/ //指针的指向不能修改
-
const 既修饰指针,又修饰常量:
const 数据类型 * const 指针名
那就,都不能改呗
char c = '\n'; const char * const cp = &c;
4.1.4 指针和数组
可以利用指针访问数组的元素
char waifusWish[] = { '雾', '切', '之', '回', '光'};
char * p = waifuWish; //[1]
for (int i = 0; i < sizeof(waifuWish) / sizeof(char); i++) {
cout << *p++; //[2]
}
-
指针指向数组首地址。
——见 [3.2.1.1 数组名]
-
通过指针访问数组元素
由于数组的空间是连续的,指针自增时,会来到下一个元素的位置
4.1.5 指针和函数
利用指针作为函数参数,可以修改实参的值
地址传递:
void swap(int * a; int * b); //用两个指针接收两个地址
int main() {
int n1 = 10;
int n2 = 100;
swap(&n1; &n2); //参数中写入地址
}
void swap(int * a; int * b) { //这个场合,修改了实参的值
int temp = *a;
*a = *b;
*b = temp;
}
4.1.6 指针、数组和函数
示意一个冒泡排序:
void swap(int* a, int* b);
void bubbleSort(int* arr, int len);
int main(){
int arr[] = {3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,8,4,6,2,6};
int len = sizeof(arr) / sizeof(int);
bubbleSort(arr, len);
return 0;
}
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
void bubbleSort(int* arr, int len) {
for (int i = 0; i < len - 1; i++) {
for (int k = 0; k < len - 1; k++) {
if (*(arr + k) > *(arr + k + 1)) {
swap(arr + k, arr + k + 1);
}
}
}
}
4.2 结构体
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
4.2.1 结构体的定义
语法:struct 结构体名 {结构体成员列表};
struct Character {
int life;
int atk;
int prof;
double crit;
double crid;
};
结构体的成员可以是另一个结构体
4.2.2 创建结构体变量
通过结构体创建变量的方式有三种:
-
struct 结构体名 变量名;
int main(){ Character keqing; //这个场合,struct 关键字可以省略 keqing.life = 18716; keqing.prof = 61; keqing.atk = 2328; keqing.crit = 74.4; keqing.crid = 168.5; ... }
-
struct 结构体名 变量名 = {成员1值, 成员2值...};
int main(){ struct Character ganyu = {14577, 2474, 176, 72.7, 166.9}; //这里,struct 关键字也可以省略 ... }
-
定义结构体时顺便创建变量
struct Character { int life; int atk; int prof; double crit; double crid; }hutao; int main(){ hutao.lif = 34641; hutao.atk = 1059; hutao.prof = 82; hutao.crit = 73.0; hutao.crid = 212.1; }
4.2.3 结构体指针
通过指针访问结构体成员
操作符
->
可以实现通过指针访问结构中的属性
struct S1 {
int n1;
int n2;
};
int main() {
S1 arr[] = { {0, 10}, {1, 11} }; //[1]
S1* p = arr; //[2]
p->n1 = -50; //[3]
return 0;
}
- 一个结构体数组
- 这里,p 相当于指向 arr[0] 的地址
- 这个场合,arr[0].n1 改变了
4.2.4 结构体做函数参数
不写了,就一点:值传递不影响原变量、地址传递影响原变量
4.2.5 const 修饰结构体
用 const 防止误操作
#include<iostream>
using namespace std;
struct St {
int n;
char c;
};
void print(const St * p); //[1]
int main() {
St str = {10, 'i'};
print(&str);
return 0;
}
void print(const St * p) {
cout << p->n << '\t' << p->c << endl;
/* *p->n = 100; 因为加了 const,这个会报错*/
}
-
用 const 保证该指针值不会被修改
——见 [4.1.3.1 常量指针]