<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 修饰指针有三种情况:

  1. const 修饰指针(常量指针):const 数据类型 * 指针名

    常量指针:指针的 指向 可以修改,但指针 指向的值 不能修改

    double d = 1.5;
    const double * dp = &d;			//常量指针
    double d2 = 3.5;
    dp = &d2;						//指针的指向可以修改
    /*dp = 2.5;	这个不行*/			//指针指向的值不能修改
  2. const 修饰常量(指针常量):数据类型 * const 指针名

    指针常量:指针 指向的值 可以修改,但指针的 指向 不能修改

    int i = 10;
    int * const ip = &i;			//指针常量
    *ip = 15;						//指针指向的值可以修改
    int n = 25;
    /*ip = &n;	这个不行*/			//指针的指向不能修改
  3. 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]
}
  1. 指针指向数组首地址。

    ——见 [3.2.1.1 数组名]

  2. 通过指针访问数组元素

    由于数组的空间是连续的,指针自增时,会来到下一个元素的位置

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;
}
  1. 一个结构体数组
  2. 这里,p 相当于指向 arr[0] 的地址
  3. 这个场合,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,这个会报错*/
}
  1. 用 const 保证该指针值不会被修改

    ——见 [4.1.3.1 常量指针]


<C++>4 指针和结构体
https://i-melody.github.io/2022/03/31/C++/入门阶段/4 指针和结构体/
作者
Melody
发布于
2022年3月31日
许可协议