大家好,欢迎来到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