MST

星途 面试题库

面试题:C语言指针常量在复杂数据结构中的特性及应用

在一个包含结构体嵌套链表的复杂数据结构中,定义一个指针常量指向链表头节点。要求写出结构体定义、链表创建函数、遍历函数,并在遍历函数中通过指针常量安全地访问和操作链表节点的数据。阐述指针常量在这种复杂场景下的特性以及如何确保数据结构的完整性和安全性。
38.4万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
#include <stdio.h>
#include <stdlib.h>

// 定义结构体
typedef struct InnerStruct {
    int data;
    struct InnerStruct *next;
} InnerStruct;

typedef struct OuterStruct {
    InnerStruct *listHead;
} OuterStruct;

// 创建链表函数
InnerStruct* createInnerList(int numNodes) {
    InnerStruct *head = NULL;
    InnerStruct *tail = NULL;

    for (int i = 0; i < numNodes; i++) {
        InnerStruct *newNode = (InnerStruct*)malloc(sizeof(InnerStruct));
        newNode->data = i;
        newNode->next = NULL;

        if (head == NULL) {
            head = newNode;
            tail = newNode;
        } else {
            tail->next = newNode;
            tail = newNode;
        }
    }
    return head;
}

// 遍历函数
void traverseList(const InnerStruct * const head) {
    const InnerStruct *current = head;
    while (current != NULL) {
        printf("Data: %d\n", current->data);
        current = current->next;
    }
}

int main() {
    OuterStruct outer;
    outer.listHead = createInnerList(5);

    const InnerStruct * const listHeadConst = outer.listHead;
    traverseList(listHeadConst);

    // 释放链表内存
    InnerStruct *current = outer.listHead;
    InnerStruct *next;
    while (current != NULL) {
        next = current->next;
        free(current);
        current = next;
    }

    return 0;
}

指针常量在这种复杂场景下的特性

  1. 指针不可变:指针常量一旦初始化,其指向不能改变。在上述代码中 const InnerStruct * const headhead 既不能指向其他 InnerStruct 节点,也不能被重新赋值。这确保了链表的遍历顺序不会被意外改变,维持了链表结构的完整性。
  2. 数据可访问性:虽然指针本身不可变,但如果指针指向的是可变数据类型(如 InnerStruct 中的 data 成员),只要没有将整个结构体声明为 const,数据成员是可以被修改的。在遍历函数中,我们使用 const 修饰指针,使得链表结构不会被意外修改,但可以安全地访问节点数据。

如何确保数据结构的完整性和安全性

  1. 使用 const 修饰:通过 const InnerStruct * const head 这样的声明,限制了指针的可变性,防止误操作导致链表结构被破坏。例如,避免了将链表头指针错误地指向其他地方,保证链表从固定的头节点开始遍历。
  2. 内存管理:在创建链表时,正确分配内存,并在使用完链表后,通过遍历链表释放每一个节点的内存,避免内存泄漏。这有助于维持数据结构在整个生命周期内的完整性和安全性。