详解C语言指针(下):指针解引用,二级指针(结合近些年笔/面试的实际例子)


🔥个人主页艾莉丝努力练剑

❄专栏传送门:《C语言》《数据结构与算法》C语言刷题12天IO强训LeetCode代码强化刷题C/C++干货分享&学习过程记录

🍉学习方向:C/C++方向

⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平


 C++的两个参考文档:

老朋友(非官方文档):cplusplus

官方文档(同步更新):cppreference



目录

一、指针解引用的本质

大厂常见坑点案例

二、二级指针的实战理解

二级指针与二维数组

三、指针解引用的案例

1、结构体指针解引用

2、指针解引用与类型转换

四、二级指针的经典应用

1、动态字符串数组

2、修改外部指针

五、必须掌握的指针操作技巧

1、指针偏移解引用

2、多级解引用

六、常见错误及排查方法

七、性能优化


一、指针解引用的本质

指针解引用(*操作)实际上是通过地址访问内存的过程。每次解引用都相当于一次"寻址-取值"操作。记住这个核心原则:

解引用前必须确保指针指向有效的内存区域

大厂常见坑点案例

这里我们以腾讯2023面试题为例:

int *p = NULL;
*p = 10; 

问:会发生什么?

答案:触发段错误(Segmentation Fault),因为试图访问0地址的内存。

实际工程项目中指针解引用的正确用法:

int value = 100;
int *p = &value;  // 先让指针指向有效地址
printf("%d", *p); // 安全解引用

二、二级指针的实战理解

二级指针就是“指向指针的指针”,在以下场景特别有用——

1、需要修改指针本身时;

2、处理指针数组时;

3、动态分配二维数组时。

这里展示一个阿里巴巴高频面试案例:

void allocate_memory(char **ptr, int size) 
{
    *ptr = (char*)malloc(size); // 通过二级指针修改外部指针
}

int main() 
{
    char *str = NULL;
    allocate_memory(&str, 100); // 传入指针的地址
    strcpy(str, "Alibaba");
    free(str);
}

二级指针与二维数组

下面这个字节跳动2024年的一道笔试真题:

int arr[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
int (*p)[4] = arr;  // 数组指针
int **pp = (int**)arr; // 这种转换是否正确?

printf("%d", arr[1][2]);  // 正确
printf("%d", *(*(arr+1)+2)); // 正确
printf("%d", pp[1][2]);   // 可能崩溃!

关键点:注意二维数组不是二级指针!它们的内存布局完全不同。

三、指针解引用案例

1、结构体指针解引用

下面这道题是美团的一个真实工程案例:

typedef struct 
{
    int id;
    char name[20];
} Employee;

Employee e = {1001, "张三"};
Employee *p = &e;

// 两种访问方式对比
printf("%s", (*p).name);  // 传统方式
printf("%s", p->name);    // 更推荐的箭头语法

2、指针解引用与类型转换

下面这道是华为安全部门的一道考题:

float f = 3.14;
int *p = (int*)&f;
printf("%d", *p); // 输出什么?

答案:输出浮点数的二进制表示(IEEE 754编码)的整数值。

四、二级指针经典应用

1、动态字符串数组

下面是腾讯云面试实战的一道题:

char **create_string_array(int count) 
{
    char **arr = (char**)malloc(count * sizeof(char*));
    for(int i=0; i<count; i++) 
    {
        arr[i] = (char*)malloc(50 * sizeof(char));
        sprintf(arr[i], "String%d", i+1);
    }
    return arr;
}

// 释放时也要二级指针操作
void free_string_array(char **arr, int count) 
{
    for(int i=0; i<count; i++) 
    {
        free(arr[i]);
    }
    free(arr);
}

2、修改外部指针

下面是百度搜索部门考题:

void change_pointer(int **pptr) 
{
    static int value = 100;
    *pptr = &value; // 修改外部指针的指向
}

int main() 
{
    int *ptr = NULL;
    change_pointer(&ptr);
    printf("%d", *ptr); // 输出100
}

五、指针操作技巧掌握要领

1、指针偏移解引用

下面是拼多多2023年的一道笔试题:

int arr[] = {10,20,30,40,50};
int *p = arr;

printf("%d", *(p + 2));  // 30
printf("%d", p[2]);      // 30 (等价写法)
printf("%d", 2[p]);      // 30 (这种写法也是合法的!)

2、多级解引用

下面是阿里“双11”的一道压测题:

int value = 999;
int *p1 = &value;
int **p2 = &p1;
int ***p3 = &p2;

printf("%d", ***p3); // 999
// 解析过程:
// 1. *p3得到p2
// 2. *p2得到p1
// 3. *p1得到value

六、常见错误及排查方法

1、悬垂指针问题:

int *create_int() 
{
    int x = 10;
    return &x; // 返回局部变量地址!
} // 函数结束后x的内存被回收

// 正确做法:使用static或动态分配

2、指针运算错误:

char str[] = "hello";
int *p = (int*)str;
p++; // 移动了4字节!可能破坏字符串结构

3、解引用未初始化指针:

int *p; // 未初始化
*p = 10; // 随机写入内存,是非常危险的!

七、性能优化

1、减少不必要的解引用操作:

// 不好的写法
for(int i=0; i<100; i++) 
{
    sum += *ptr;
    ptr++;
}

下面就是优化之后的写法——

// 优化写法
int temp = *ptr;
for(int i=0; i<100; i++) 
{
    sum += temp;
    temp = *(++ptr);
}

2、使用restrict关键字(C99):

void copy_array(int *restrict dest, int *restrict src, int n) 
{
    // 告诉编译器两个指针不会重叠
    for(int i=0; i<n; i++) 
    {
        dest[i] = src[i];
    }
}

    往期回顾:

    详解C语言指针(上):(含大厂面试实战哦!)指针运算、指针和数组、多级函数

    结语:本期内容到这里就结束了,希望对大家有帮助!

    评论 1
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值