MST

星途 面试题库

面试题:C语言指针、间接访问与左值的深度剖析

在C语言中,考虑以下代码片段: ```c int *func() { int a = 10; return &a; } ``` 这段代码存在什么问题?从指针、间接访问和左值的角度详细分析。如果要正确返回一个指向局部变量的指针,应该如何修改代码(假设在堆上分配内存)?并且阐述在这个过程中指针、间接访问和左值的行为变化。
31.5万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

代码存在的问题

  1. 指针方面:函数 func 返回了一个指向局部变量 a 的指针。局部变量 a 在函数结束时其生命周期结束,被销毁。此时返回的指针指向的是一块已经无效的内存区域,成为了悬空指针。后续使用这个指针进行间接访问会导致未定义行为。
  2. 间接访问方面:当函数调用结束后,若通过返回的指针进行间接访问,如 int b = *func();,由于指针指向的内存已无效,访问这块内存会导致程序崩溃或出现难以预料的结果,因为这块内存可能已被其他程序部分复用。
  3. 左值方面a 是一个左值,在函数返回后,它作为左值的意义已经不存在,因为其存储空间已被释放。试图通过返回的指针将其作为左值使用,如 *func() = 20; 不仅会因为悬空指针导致未定义行为,而且即使指针有效,这种操作也违背了左值的生命周期逻辑。

修改代码以正确返回指向局部变量的指针(在堆上分配内存)

#include <stdlib.h>

int *func() {
    int *a = (int *)malloc(sizeof(int));
    if (a == NULL) {
        // 处理内存分配失败的情况
        return NULL;
    }
    *a = 10;
    return a;
}

指针、间接访问和左值行为变化

  1. 指针方面:通过 malloc 在堆上分配内存,返回的指针指向堆上的有效内存区域,其生命周期不再受函数结束的影响。只要不调用 free 释放这块内存,指针始终有效。
  2. 间接访问方面:通过返回的指针进行间接访问是安全的,如 int b = *func(); 能正确获取到堆上存储的值 10。因为指针指向的堆内存没有被释放,直到显式调用 free
  3. 左值方面:分配在堆上的内存可以通过指针作为左值使用,如 *func() = 20; 是合法的操作,它会修改堆上存储的值。但使用完后必须调用 free 释放内存,否则会导致内存泄漏。例如:
int *ptr = func();
if (ptr!= NULL) {
    *ptr = 20;
    // 使用完后释放内存
    free(ptr);
    ptr = NULL;
}