struct 赋值 做函数参数

本文介绍了一个C语言示例程序,演示了如何使用结构体,并探讨了结构体变量作为函数参数时的两种方式:按值传递和按地址传递。通过具体的代码实例,展示了这两种方式对原始结构体数据的影响。
#include <stdio.h>
#include <stdlib.h>

struct date{
	int year;
	int month;
	int day;
};

typedef struct date date;

date birth_date = {2012, 9, 26};

void struct_by_value(date date_copy){
	date_copy.year = 2000;
	printf("date_copy.year = %d\n", date_copy.year);
}

void struct_by_ptr(date *date_ptr){
	date_ptr->year = 3000;
	printf("date_ptr->year = %d\n", date_ptr->year);
}

void test_by_value_ptr_to_func(){
	printf("birth_date.year = %d\n", birth_date.year);
	struct_by_value(birth_date);
	printf("after by copy, birth_date.year = %d\n", birth_date.year);
	struct_by_ptr(&birth_date);
	printf("after by ptr, birth_date.year = %d\n", birth_date.year);
}

void test_by_value_ptr_equal(){
	printf("birth_date.year = %d\n", birth_date.year);
	date another_date = birth_date;
	another_date.year = 2013;
	printf("after value equals, birth_date.year = %d\n", birth_date.year);
	date *a_date_ptr = &birth_date;
	a_date_ptr->year = 4000;
	printf("after ptr equals, birth_date.year = %d\n", birth_date.year);
}


int main(void){
	test_by_value_ptr_to_func();
	puts("==========================");
	test_by_value_ptr_equal();
	puts("==========================");
}


结构体 变量可以像常规类型的变量(int a) 一样赋值 =, 做函数参数。

通过变量复制(复制内存) 或者 通过指针。

<think> 我们被要求讲解C语言中结构体的定义以及在函数参数中使用结构体的方法。根据引用内容,我们可以总结如下: 1. 结构体定义:使用`struct`关键字定义自定义数据类型,可以包含多个不同类型的成员。 2. 结构体变量:定义结构体类型的变量,并访问其成员。 3. 结构体作为函数参数:可以将结构体变量、结构体指针作为参数传递给函数。 下面我们按照步骤详细说明: ### 1. 结构体的定义 结构体定义的基本语法: ```c struct 结构体标签 { 数据类型 成员1; 数据类型 成员2; // ... 更多成员 }; ``` 例如,定义一个表示学生的结构体: ```c struct Student { char name[50]; int age; float score; }; ``` ### 2. 结构体变量的定义 定义结构体变量有两种常用方式: - 在定义结构体类型的同时定义变量 - 先定义结构体类型,再定义变量 ```c // 方式1: 定义类型同时定义变量 struct Student { char name[50]; int age; float score; } student1, student2; // 方式2: 先定义类型,再定义变量 struct Student student3; ``` ### 3. 结构体成员访问 - 使用`.`操作符访问结构体变量的成员 - 如果是指向结构体的指针,则使用`->`操作符 ```c // 结构体变量访问 struct Student s1; strcpy(s1.name, "Alice"); // 注意:字符串赋值使用strcpy s1.age = 20; s1.score = 90.5; // 结构体指针访问 struct Student *p = &s1; printf("Name: %s\n", p->name); printf("Age: %d\n", p->age); ``` ### 4. 结构体作为函数参数 结构体可以作为函数参数,传递方式有两种: - 直接传递结构体(值传递) - 传递结构体指针(地址传递) #### 值传递示例: ```c // 定义函数 void printStudent(struct Student s) { printf("Name: %s\n", s.name); printf("Age: %d\n", s.age); printf("Score: %.2f\n", s.score); } // 调用 printStudent(s1); ``` 注意:值传递会复制整个结构体,如果结构体很大,效率较低。 #### 地址传递示例(推荐方式): ```c // 定义函数 void printStudentByPointer(const struct Student *s) { printf("Name: %s\n", s->name); printf("Age: %d\n", s->age); printf("Score: %.2f\n", s->score); } // 调用 printStudentByPointer(&s1); ``` 使用指针传递可以避免结构体的复制,提高效率。同时,使用`const`修饰指针可以防止在函数内修改结构体内容。 ### 5. 结构体的初始化 结构体变量可以在定义时初始化: ```c struct Student s2 = {"Bob", 21, 88.5}; ``` ### 6. 注意事项 - 结构体的大小可能包含填充字节(内存对齐)[^3] - 结构体成员默认是公有的(C语言没有访问控制修饰符) - 结构体可以嵌套,即一个结构体的成员可以是另一个结构体 ### 示例程序 下面是一个完整的示例程序,演示结构体的定义、初始化、作为函数参数传递: ```c #include <stdio.h> #include <string.h> // 定义结构体 struct Student { char name[50]; int age; float score; }; // 函数:打印学生信息(使用结构体指针) void printStudent(const struct Student *s) { printf("Name: %s\n", s->name); printf("Age: %d\n", s->age); printf("Score: %.2f\n", s->score); } // 函数:修改学生年龄(使用结构体指针) void changeAge(struct Student *s, int newAge) { s->age = newAge; } int main() { // 初始化结构体变量 struct Student stu1 = {"Alice", 20, 90.5}; // 打印初始信息 printf("Original:\n"); printStudent(&stu1); // 修改年龄 changeAge(&stu1, 21); printf("\nAfter change:\n"); printStudent(&stu1); return 0; } ``` 输出: ``` Original: Name: Alice Age: 20 Score: 90.50 After change: Name: Alice Age: 21 Score: 90.50 ``` ### 相关问题 1. 结构体与联合体(union)有什么区别? 2. 如何计算结构体的大小?内存对齐的原则是什么? 3. 结构体数组如何定义和使用? 4. C语言中如何实现结构体的深拷贝? </think> ### C语言结构体定义与函数参数使用指南 #### 一、结构体定义 结构体是自定义的复合数据类型,允许存储不同类型的数据项。定义语法: ```c struct 结构体标签 { 数据类型 成员1; 数据类型 成员2; // ... 更多成员 }; ``` **示例**:定义学生结构体 ```c struct Student { char name[50]; // 字符串成员 int age; // 整型成员 float gpa; // 浮点型成员 }; ``` **类型定义+变量创建**(常用方式): ```c typedef struct { int x; int y; } Point; // 定义Point类型 Point p1; // 创建结构体变量 ``` #### 二、结构体变量使用 通过`.`操作符访问成员: ```c struct Student s1; strcpy(s1.name, "Alice"); // 字符串赋值 s1.age = 20; s1.gpa = 3.8; printf("Name: %s, Age: %d\n", s1.name, s1.age); ``` #### 三、结构体作为函数参数 ##### 1. 值传递(复制整个结构体) ```c void printStudent(struct Student s) { printf("Name: %s\n", s.name); // 访问副本数据[^1] } // 调用 printStudent(s1); ``` *⚠️ 缺点:大结构体复制效率低* ##### 2. 指针传递(推荐方式) ```c void modifyStudent(struct Student *s_ptr) { s_ptr->age += 1; // 使用->操作符修改原数据[^2] // 等价于 (*s_ptr).age += 1; } // 调用 modifyStudent(&s1); // 传递地址 ``` *✅ 优势:避免复制开销,可直接修改原结构体* ##### 3. 结构体数组作为参数 ```c void printClass(struct Student arr[], int size) { for (int i = 0; i < size; i++) { printf("%s: %d years\n", arr[i].name, arr[i].age); } } // 调用 struct Student class[30]; printClass(class, 30); ``` #### 四、结构体初始化方法 **初始化方式**: ```c // 顺序初始化 struct Student s2 = {"Bob", 21, 3.5}; // 指定成员初始化(C99+) struct Student s3 = {.name = "Charlie", .gpa = 3.9}; // 动态初始化 struct Student *s4 = malloc(sizeof(struct Student)); s4->age = 22; ``` #### 五、关键注意事项 1. **内存对齐**:结构体大小可能大于成员总和(填充字节)[^3] ```c struct Example { char c; int i; }; printf("Size: %zu\n", sizeof(struct Example)); // 可能输出8而非5 ``` 2. **深浅拷贝**: ```c Point a = {1, 2}; Point b = a; // 浅拷贝(值复制) ``` 3. **嵌套结构体**: ```c typedef struct { Point start; Point end; } LineSegment; ``` 4. **const指针参数**(防止意外修改): ```c void readOnlyAccess(const struct Student *s) { printf("Name: %s\n", s->name); // 允许读取 // s->age = 0; // 编译错误(禁止修改) } ``` #### 六、完整示例 ```c #include <stdio.h> #include <string.h> typedef struct { char title[100]; int pages; } Book; // 指针传递修改结构体 void increasePages(Book *book, int added) { book->pages += added; } int main() { Book myBook = {"The C Language", 300}; increasePages(&myBook, 50); // 传递指针 printf("书名: %s, 页数: %d\n", // 输出:书名: The C Language, 页数: 350 myBook.title, myBook.pages); return 0; } ``` #### 七、常见问题解答 **Q:结构体与联合体(union)有何区别?** A:结构体成员独立存储(内存叠加),联合体成员共享内存(仅存1个成员值) **Q:如何动态创建结构体数组?** ```c struct Student *group = malloc(5 * sizeof(struct Student)); group[0].age = 20; // 访问首元素 ``` **Q:结构体作为返回值?** ```c Point createPoint(int x, int y) { Point p = {x, y}; return p; // 返回整个结构体(编译器优化后效率尚可) } ``` --- ### 相关问题 1. 结构体与联合体(union)在内存使用上有何本质区别? 2. 如何计算包含位域的结构体大小? 3. C语言中结构体对齐(alignment)的规则是什么? 4. 在函数内部动态分配的结构体如何安全返回?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值