斩C—带你深刻理解指针

文章目录

  • 一、什么是指针
      • **1. 指针的基本概念**
      • **2. 步长的决定因素**
      • **3. 常见类型的指针步长**
        • **1. `char*` 指针**
        • **2. `int*` 指针**
        • **3. `double*` 指针**
  • 二、指针的级别
    • 1.一级指针
    • 2.二级指针
    • **二级指针的使用场景**
    • 3.多级指针
  • 三、指针的类型

一、什么是指针

1. 指针的基本概念

指针的本质:指针是一个变量,存储的是另一个变量的内存地址。

解引用:通过指针访问其指向的内存地址中的数据。

步长:当指针进行算术运算(如 p++p + 1)时,指针移动的字节数。


2. 步长的决定因素

指针的步长由以下两个因素决定:

  1. 指针的类型:指针指向的数据类型决定了每次解引用时访问的内存大小。
  2. 系统架构:不同系统(如32位或64位)中,指针变量本身的大小可能不同,但步长主要由指针类型决定。

​ 在 C 语言中,每个变量都有一个存储位置,也就是它在内存中的地址。比如你定义一个变量 int a = 5;,它就占据了内存中的某个位置,这个位置有一个唯一的地址。指针就是用来存储这个地址的。指针是一个变量,它保存的是另一个变量的内存地址。定义指针时,需要指定它指向的变量类型。例如,int *p; 这表示 p 是一个指向 int 类型变量的指针。(也可以抽象成一根针指向a所占据的地址)
可以理解为以下两种方式:

创建一个int*pc=&a;

斩C—带你深刻理解指针_第1张图片

为什么a前面会出现一个&符号?又是什么?——&是取地址符,&a也就是把a的地址取出来赋值给pc,*说明pc是一个指针,int说明pc这根针指向的地址内部存储的是int型;

a是一个整型变量,整型变量占用4个字节,每个字节都有地址,那&a取出来的是哪一个地址呢?——取出的是第一个字节的地 (较小的地址);

*pc可以找到a,也就是*pc=a, 如果要将a的值修改那可以直接*pc=修改值

1.在栈区随机分配一个地址存放变量a;假设为ox0012ff43,第一种方法理解为随机分配个地址给pc用来存放a的地址,注意pc也会分配一个地址;

2.把pc抽象为一根针,指着a的上层,也就是指向a的地址ox0012ff43,pc也会分配一个地址,同上;

注意二者等价

3. 常见类型的指针步长

以下是常见数据类型的指针步长示例(假设在32位或64位系统中,int 占4字节,char 占1字节,double 占8字节):

1. char* 指针

类型大小char 占1字节。

步长:每次 p++p + 1,指针移动1字节。

示例

c

char arr[] = {'a', 'b', 'c'};
char *p = arr; // p指向arr[0]
p++;           // p现在指向arr[1],移动1字节
2. int* 指针

类型大小int 占4字节。

步长:每次 p++p + 1,指针移动4字节。

示例

int arr[] = {10, 20, 30};
int *p = arr; // p指向arr[0]
p++;          // p现在指向arr[1],移动4字节
3. double* 指针

类型大小double 占8字节。

步长:每次 p++p + 1,指针移动8字节。

示例

double arr[] = {1.1, 2.2, 3.3};
double *p = arr; // p指向arr[0]
p++;             // p现在指向arr[1],移动8字节

用法:定义一个int a = 0x11223344 ;

变量存储在内存单元如图:

斩C—带你深刻理解指针_第2张图片

这里相信大家有疑问,为什么不是11223344呢,是因为变量存储在内存单元中存在大小端问题,可参考——大小端

如果我们只是想改变其中一个字节的数据那我们就可以将变量a强制转换为char*类型

#include 

int main() {
    int a = 0x11223344;
    char *p = (char *)&a; // 将int指针强制转换为char指针

    printf("Before: a = 0x%x\n", a);

    p[1] = 0xAA; // 修改第1字节为0xAA

    printf("After: a = 0x%x\n", a);

    return 0;
}

输出:

Before: a = 0x11223344
After: a = 0x1122aa44

想修改几个字节就强制转换为所对应步长的类型;

二、指针的级别

1.一级指针

以上述说的都是一级指针,只有一颗*

就不再赘述;

2.二级指针

顾名思义就有2颗*

二级指针是指 指向指针的指针。在C语言中,指针是一个变量,存储的是另一个变量的地址;而二级指针存储的是一个指针变量的地址。

一级指针:指向普通变量(如 int* 指向 int)。

二级指针:指向指针变量(如 int** 指向 int*)。
斩C—带你深刻理解指针_第3张图片

int **pc; // pc 是一个二级指针,指向一个 int* 类型的指针
类型 **指针变量名;

int *p =& a ; int **pc= & pc ;

二级指针的使用场景

  1. 动态分配二维数组
  2. 修改指针变量的值(通过函数传递指针的地址)。
  3. 管理指针数组

修改指针变量的值

通过二级指针,可以在函数中修改指针变量的值。

#include 
#include 

void allocateMemory(int **ptr) {
    *ptr = (int *)malloc(sizeof(int)); // 分配内存
    **ptr = 100; // 修改指针指向的值
}

int main() {
    int *p = NULL;
    allocateMemory(&p); // 传递指针的地址
    printf("Value: %d\n", *p); // 输出 100
    free(p); // 释放内存
    return 0;
}

allocateMemory 函数接收一个二级指针 int **ptr

*ptr 解引用后得到一级指针 int*,可以修改它的值。

**ptr 解引用后得到 int 类型的值。

使用二级指针动态分配二维数组。

#include 
#include 

int main() {
    int rows = 3, cols = 4;
    int **arr;

    // 分配行指针
    arr = (int **)malloc(rows * sizeof(int *));

    // 为每一行分配列
    for (int i = 0; i < rows; i++) {
        arr[i] = (int *)malloc(cols * sizeof(int));
    }

    // 赋值
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            arr[i][j] = i * cols + j;
        }
    }

    // 打印
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }

    // 释放内存
    for (int i = 0; i < rows; i++) {
        free(arr[i]);
    }
    free(arr);

    return 0;
}
  • arr 是一个二级指针,指向一个指针数组。

  • 首先为行分配内存,然后为每一行分配列。

  • 通过 arr[i][j] 访问二维数组元素。

  • 最后逐行释放内存。

  • **通过二级指针返回动态分配的指针。

    #include 
    #include 
    
    void createArray(int **arr, int size) {
        *arr = (int *)malloc(size * sizeof(int)); // 分配内存
        for (int i = 0; i < size; i++) {
            (*arr)[i] = i * 2; // 初始化数组
        }
    }
    
    int main() {
        int *arr = NULL;
        int size = 5;
    
        createArray(&arr, size); // 传递指针的地址
    
        for (int i = 0; i < size; i++) {
            printf("%d ", arr[i]); // 输出 0 2 4 6 8
        }
    
        free(arr); // 释放内存
        return 0;
    }
    

    createArray 函数通过二级指针 int **arr 返回动态分配的数组。

    *arr 解引用后得到一级指针 int*,可以操作动态数组。

3.多级指针

由于c语言并不要求我们学习多级指针,且多级指针复杂难懂,这里就不再赘述,感兴趣的佬可参考 多级指针解析

要求我们学习多级指针,且多级指针复杂难懂,这里就不再赘述,感兴趣的佬可参考 多级指针解析**

三、指针的类型

int*

char*

double*

float*

以上类型开头讲述过,还有void*等特殊指针也不再赘述

点赞关注不迷路哦 !!!

斩C—带你深刻理解指针_第4张图片

你可能感兴趣的:(c语言,c++)