“列表”在C语言中没有一个内置的、像其他高级语言那样的数据类型,它需要我们自己使用更基础的数据结构来实现,最常见和灵活的实现方式是链表。

(图片来源网络,侵删)
下面,我将分步解释如何创建一个空链表,并提供完整的代码示例。
核心概念:什么是“空列表”?
一个“空列表”意味着列表中不包含任何元素,对于链表来说,这通常意味着它的“头指针”(Head Pointer)不指向任何有效的节点,而是指向 NULL。
创建一个空列表的核心步骤就是:
- 定义一个链表节点的结构体。
- 定义一个指向链表头的指针。
- 将这个头指针初始化为
NULL。
第一步:定义链表节点
链表是由一个个“节点”串联而成的,每个节点至少包含两部分信息:

(图片来源网络,侵删)
- 数据:节点存储的实际内容,可以是整数、浮点数、字符,甚至是复杂的结构体。
- 指针:指向下一个节点的地址。
我们使用 struct 来定义节点结构体。
// 定义一个链表节点的结构体
typedef struct Node {
int data; // 数据部分,这里我们用 int 作为示例
struct Node* next; // 指针部分,指向下一个节点
} Node;
typedef为struct Node创建了一个别名Node,这样我们后面可以直接用Node来声明变量,更简洁。data是我们想存储的数据。next是一个指向Node结构体类型的指针,用于链接下一个节点。
第二步:创建并初始化空列表
现在我们有了节点的“蓝图”,接下来就是创建列表本身,我们只需要一个指针来记录列表的开头即可。
// 定义一个指向链表头部的指针 Node* head = NULL;
关键点:将 head 指针初始化为 NULL,这个动作本身就创建了一个空列表,因为 head 不指向任何有效的节点,表示列表为空。
第三步:封装成函数(良好实践)
在实际编程中,我们通常会把创建空列表的操作封装成一个函数,这样代码更清晰、更易于复用。

(图片来源网络,侵删)
这个函数不需要任何参数,它的任务就是返回一个 NULL 指针,代表一个空列表。
/**
* @brief 创建一个空链表
* @return 返回一个 NULL 指针,表示一个空列表
*/
Node* createEmptyList() {
return NULL;
}
完整代码示例
下面是一个完整的、可运行的C程序,它演示了如何定义节点、创建空列表,并提供了一个打印列表的函数来验证列表确实是空的。
#include <stdio.h>
#include <stdlib.h> // 需要包含这个头文件来使用 malloc
// 1. 定义链表节点的结构体
typedef struct Node {
int data; // 数据部分
struct Node* next; // 指向下一个节点的指针
} Node;
// 2. 函数:创建一个空链表
// 这个函数返回一个 NULL 指针,代表空列表
Node* createEmptyList() {
printf("一个空列表已创建,\n");
return NULL;
}
// 3. 函数:打印链表中的所有元素
// 如果列表为空,它会打印提示信息
void printList(Node* head) {
Node* current = head; // 从头节点开始遍历
if (current == NULL) {
printf("列表为空,没有元素可打印,\n");
return;
}
printf("列表中的元素: ");
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next; // 移动到下一个节点
}
printf("NULL\n"); // 打印列表的结尾
}
// 主函数
int main() {
// 4. 在 main 函数中调用 createEmptyList() 来创建一个空列表
Node* myList = createEmptyList();
// 5. 验证列表是否为空
printList(myList);
return 0;
}
如何编译和运行
- 将以上代码保存为
create_list.c。 - 打开终端或命令提示符。
- 使用GCC编译器进行编译:
gcc create_list.c -o create_list - 运行生成的可执行文件:
./create_list(在Windows上是create_list.exe)
预期输出
一个空列表已创建。
列表为空,没有元素可打印。
进阶:如何向空列表中添加元素?
创建空列表只是第一步,通常我们接下来会向列表中添加元素,最简单的添加方式是在头部插入。
// 函数:在链表头部插入一个新节点
Node* insertAtHead(Node* head, int newData) {
// 1. 创建一个新节点
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
printf("内存分配失败!\n");
return head; // 内存不足,返回原来的头指针
}
// 2. 设置新节点的数据和指针
newNode->data = newData;
newNode->next = NULL;
// 3. 如果列表为空(head为NULL),新节点就是头节点
if (head == NULL) {
head = newNode;
} else {
// 4. 如果列表不为空,将新节点连接到原来的头部
newNode->next = head;
head = newNode; // 更新头指针,使其指向新节点
}
return head; // 返回新的头指针
}
如何在 main 函数中使用
int main() {
// 创建一个空列表
Node* myList = createEmptyList();
// 向空列表中添加元素
myList = insertAtHead(myList, 10); // 列表: 10
myList = insertAtHead(myList, 20); // 列表: 20 -> 10
myList = insertAtHead(myList, 30); // 列表: 30 -> 20 -> 10
// 打印列表,验证添加结果
printList(myList);
return 0;
}
预期输出
一个空列表已创建。
列表中的元素: 30 -> 20 -> 10 -> NULL
在C语言中创建一个空列表,其本质是:
- 定义节点结构:使用
struct包含数据和指向下一个节点的指针。 - 初始化头指针:将一个指向节点类型的指针(如
Node* head)设置为NULL。
这个过程可以封装成一个简单的函数 createEmptyList(),它返回 NULL,代表一个空的链表,这是所有链表操作的基础。
