C语言:结构体指针

C语言:结构体指针C 语言 结构体指针 结构体指针

大家好,欢迎来到IT知识分享网。

介绍

在C语言中,结构体指针是一种非常有用的工具,它允许我们通过指针来操作结构体,尤其是在处理动态内存分配或函数参数传递时。以下是关于C语言结构体指针的详细讲解。

定义结构体指针

首先,我们需要定义一个结构体。例如,定义一个表示学生信息的结构体:

#include <stdio.h> struct Student { 
    char name[50]; int age; float gpa; }; 

然后,我们可以定义一个指向该结构体的指针:

struct Student *studentPtr; 

初始化结构体指针

指向现有结构体变量

我们可以让结构体指针指向一个已有的结构体变量:

struct Student student1 = { 
   "Alice", 20, 3.5}; struct Student *studentPtr = &student1; 

动态分配内存

我们也可以使用动态内存分配来初始化结构体指针:

struct Student *studentPtr = (struct Student *)malloc(sizeof(struct Student)); if (studentPtr == NULL) { 
    printf("Memory allocation failed\n"); return 1; } 

访问结构体成员

使用结构体指针访问成员

当我们有一个结构体指针时,可以使用箭头操作符 -> 来访问结构体成员:

studentPtr->age = 21; printf("Name: %s, Age: %d, GPA: %.2f\n", studentPtr->name, studentPtr->age, studentPtr->gpa); 

通过指针和解引用

我们也可以使用指针和解引用操作符 * 组合来访问结构体成员:

(*studentPtr).age = 22; printf("Name: %s, Age: %d, GPA: %.2f\n", (*studentPtr).name, (*studentPtr).age, (*studentPtr).gpa); 

不过,使用箭头操作符 -> 更加简洁和常见。

结构体指针作为函数参数

将结构体指针作为函数参数,可以高效地传递结构体数据,避免大结构体的拷贝。以下是一个示例:

void printStudent(struct Student *student) { 
    printf("Name: %s, Age: %d, GPA: %.2f\n", student->name, student->age, student->gpa); } int main() { 
    struct Student student1 = { 
   "Alice", 20, 3.5}; printStudent(&student1); struct Student *studentPtr = (struct Student *)malloc(sizeof(struct Student)); if (studentPtr == NULL) { 
    printf("Memory allocation failed\n"); return 1; } strcpy(studentPtr->name, "Bob"); studentPtr->age = 21; studentPtr->gpa = 3.7; printStudent(studentPtr); free(studentPtr); return 0; } 

使用结构体指针构建链表

结构体指针在构建复杂数据结构(如链表)时非常有用。以下是一个简单的单链表示例:

#include <stdio.h> #include <stdlib.h> // 定义链表节点 struct Node { 
    int data; struct Node *next; }; // 创建新节点 struct Node* createNode(int data) { 
    struct Node *newNode = (struct Node *)malloc(sizeof(struct Node)); if (newNode == NULL) { 
    printf("Memory allocation failed\n"); exit(1); } newNode->data = data; newNode->next = NULL; return newNode; } // 打印链表 void printList(struct Node *head) { 
    struct Node *current = head; while (current != NULL) { 
    printf("%d -> ", current->data); current = current->next; } printf("NULL\n"); } int main() { 
    struct Node *head = createNode(1); head->next = createNode(2); head->next->next = createNode(3); printList(head); // 释放内存 struct Node *current = head; struct Node *next; while (current != NULL) { 
    next = current->next; free(current); current = next; } return 0; } 

高级用法

当然,这里有更多关于C语言结构体指针的高级用法和注意事项。

多级指针(指向指针的指针)

有时候,我们可能需要使用指向指针的指针,尤其是在处理动态二维数组或在函数中修改指针变量时。以下是一个简单的示例:

#include <stdio.h> #include <stdlib.h> struct Student { 
    char name[50]; int age; float gpa; }; void allocateStudent(struct Student **studentPtr) { 
    *studentPtr = (struct Student *)malloc(sizeof(struct Student)); if (*studentPtr == NULL) { 
    printf("Memory allocation failed\n"); exit(1); } } int main() { 
    struct Student *studentPtr = NULL; allocateStudent(&studentPtr); strcpy(studentPtr->name, "Alice"); studentPtr->age = 20; studentPtr->gpa = 3.5; printf("Name: %s, Age: %d, GPA: %.2f\n", studentPtr->name, studentPtr->age, studentPtr->gpa); free(studentPtr); return 0; } 

在这个例子中,allocateStudent 函数使用了双重指针(struct Student )来分配内存并修改指针变量。

动态二维数组

使用结构体指针可以创建动态二维数组。例如,一个表示学生成绩的二维数组:

#include <stdio.h> #include <stdlib.h> struct Grade { 
    int studentId; float score; }; int main() { 
    int rows = 3; int cols = 2; // 分配行指针数组 struct Grade **grades = (struct Grade **)malloc(rows * sizeof(struct Grade *)); if (grades == NULL) { 
    printf("Memory allocation failed\n"); return 1; } // 分配每行的列 for (int i = 0; i < rows; i++) { 
    grades[i] = (struct Grade *)malloc(cols * sizeof(struct Grade)); if (grades[i] == NULL) { 
    printf("Memory allocation failed\n"); return 1; } } // 初始化数据 for (int i = 0; i < rows; i++) { 
    for (int j = 0; j < cols; j++) { 
    grades[i][j].studentId = i * cols + j; grades[i][j].score = (i + 1) * (j + 1) * 10.0; } } // 输出数据 for (int i = 0; i < rows; i++) { 
    for (int j = 0; j < cols; j++) { 
    printf("Student ID: %d, Score: %.2f\n", grades[i][j].studentId, grades[i][j].score); } } // 释放内存 for (int i = 0; i < rows; i++) { 
    free(grades[i]); } free(grades); return 0; } 

结构体指针与链表操作

链表是一种常见的数据结构,使用结构体指针实现链表操作是一个非常好的练习。以下是一些基本的链表操作示例,包括插入和删除节点:

插入节点

void insertAtBeginning(struct Node **head, int data) { 
    struct Node *newNode = createNode(data); newNode->next = *head; *head = newNode; } void insertAtEnd(struct Node **head, int data) { 
    struct Node *newNode = createNode(data); if (*head == NULL) { 
    *head = newNode; return; } struct Node *current = *head; while (current->next != NULL) { 
    current = current->next; } current->next = newNode; } 

删除节点

void deleteNode(struct Node **head, int key) { 
    struct Node *temp = *head, *prev = NULL; // 如果头节点持有要删除的值 if (temp != NULL && temp->data == key) { 
    *head = temp->next; free(temp); return; } // 搜索要删除的节点 while (temp != NULL && temp->data != key) { 
    prev = temp; temp = temp->next; } // 如果没有找到该值 if (temp == NULL) return; // 解除链接并释放内存 prev->next = temp->next; free(temp); } 

高级链表操作

链表反转

反转链表是一个常见的操作,以下是反转单链表的代码示例:

#include <stdio.h> #include <stdlib.h> struct Node { 
    int data; struct Node *next; }; struct Node* createNode(int data) { 
    struct Node *newNode = (struct Node *)malloc(sizeof(struct Node)); if (newNode == NULL) { 
    printf("Memory allocation failed\n"); exit(1); } newNode->data = data; newNode->next = NULL; return newNode; } void reverseList(struct Node **head) { 
    struct Node *prev = NULL; struct Node *current = *head; struct Node *next = NULL; while (current != NULL) { 
    next = current->next; current->next = prev; prev = current; current = next; } *head = prev; } void printList(struct Node *head) { 
    struct Node *current = head; while (current != NULL) { 
    printf("%d -> ", current->data); current = current->next; } printf("NULL\n"); } int main() { 
    struct Node *head = createNode(1); head->next = createNode(2); head->next->next = createNode(3); printf("Original List:\n"); printList(head); reverseList(&head); printf("Reversed List:\n"); printList(head); // 释放内存 struct Node *current = head; struct Node *next; while (current != NULL) { 
    next = current->next; free(current); current = next; } return 0; } 

链表合并

合并两个有序链表是一个常见操作,以下是合并两个有序链表的代码示例:

struct Node* mergeLists(struct Node *l1, struct Node *l2) { 
    if (l1 == NULL) return l2; if (l2 == NULL) return l1; struct Node *head = NULL; if (l1->data < l2->data) { 
    head = l1; l1 = l1->next; } else { 
    head = l2; l2 = l2->next; } struct Node *current = head; while (l1 != NULL && l2 != NULL) { 
    if (l1->data < l2->data) { 
    current->next = l1; l1 = l1->next; } else { 
    current->next = l2; l2 = l2->next; } current = current->next; } if (l1 != NULL) { 
    current->next = l1; } else { 
    current->next = l2; } return head; } 

深拷贝结构体

有时候我们需要对结构体进行深拷贝,即复制结构体及其所有嵌套的内容。以下是一个深拷贝简单结构体的示例:

#include <stdio.h> #include <string.h> #include <stdlib.h> struct Address { 
    char street[100]; char city[50]; char state[50]; int zip; }; struct Student { 
    char name[50]; int age; float gpa; struct Address *address; }; struct Student* deepCopyStudent(const struct Student *original) { 
    struct Student *copy = (struct Student *)malloc(sizeof(struct Student)); if (copy == NULL) { 
    printf("Memory allocation failed\n"); exit(1); } strcpy(copy->name, original->name); copy->age = original->age; copy->gpa = original->gpa; copy->address = (struct Address *)malloc(sizeof(struct Address)); if (copy->address == NULL) { 
    printf("Memory allocation failed\n"); free(copy); exit(1); } memcpy(copy->address, original->address, sizeof(struct Address)); return copy; } int main() { 
    struct Address address = { 
   "123 Maple St", "Springfield", "IL", 62701}; struct Student student1 = { 
   "Alice", 20, 3.5, &address}; struct Student *studentCopy = deepCopyStudent(&student1); // 修改原始数据以验证深拷贝 strcpy(student1.address->city, "Changed City"); printf("Original Student: %s, %s\n", student1 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/110560.html

(0)
上一篇 2026-01-30 19:00
下一篇 2026-01-30 19:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信