假设有一个表示二维点的结构体:
struct Point {
int x;
int y;
};
然后,定义一个函数,该函数返回一个Point结构体:
struct Point create_point(int x, int y);
struct Point create_point(int x, int y) {
struct Point p;
p.x = x;
p.y = y;
return p; // 返回结构体实例
}
可以这样使用
int main() {
struct Point p1 = create_point(3, 4);
printf("Point: (%d, %d)\n", p1.x, p1.y);
return 0;
}
注!!
在C语言中,返回结构体是合法的,但是要注意返回结构体会发生值拷贝(即整个结构体的内容会被复制到接收的变量中)。如果结构体很大,可能会有效率问题。
因此:在这种情况下,可以考虑返回结构体指针(但要注意指针指向的内存生命周期)或者使用输出参数(通过指针传入结构体地址,在函数内填充)。另外,在C语言中,结构体作为函数参数和返回值时,都是按值传递的。所以上面的函数返回的是整个结构体的副本。
还有一种情况,在函数定义时,如果结构体类型是在函数返回类型中定义的(即没有提前定义),那么需要先定义结构体类型,因为函数返回类型必须是一个完整的类型。
// 错误示例:不能在返回类型中直接定义结构体
struct Point create_point(int x, int y) { ... } // 如果Point未定义,则这样写是错误的
// 正确做法:先定义结构体类型,再使用
typedef struct Point Point;
struct Point {
int x;
int y;
};
Point create_point(int x, int y) { ... }
或者将结构体定义在函数返回类型之前:
// 正确示例:在函数返回类型之前定义结构体
struct Point {
int x;
int y;
};
struct Point create_point(int x, int y) {
struct Point p = {x, y};
return p;
}
如果使用typedef,则可以直接使用类型别名:
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p = {x, y};
return p;
}
以下是完整代码示例
#include <stdio.h>
struct Point {
int x;
int y;
};
struct Point create_point(int x, int y);
struct Point create_point(int x, int y) {
struct Point p;
p.x = x;
p.y = y;
return p;
}
typedef struct {
float width;
float height;
} Rectangle;
Rectangle create_rectangle(float w, float h) {
Rectangle rect = {w, h};
return rect;
}
int main() {
struct Point p1 = create_point(3, 4);
printf("Point: (%d, %d)\n", p1.x, p1.y);
struct Point p2 = create_point(10, 20);
printf("Point: (%d, %d)\n", p2.x, p2.y);
// 使用typedef定义的结构体
Rectangle rect = create_rectangle(5.5, 3.2);
printf("Rectangle: %.1f x %.1f\n", rect.width, rect.height);
// 直接使用函数返回的结构体值
printf("Area: %.2f\n", create_rectangle(2.0, 3.0).width * create_rectangle(2.0, 3.0).height);
return 0;
}
结果
返回结构体 vs 返回结构体指针:
使用指针来传递结构体。
将结构体的指针作为函数参数传入(此时函数可以修改原结构体)
1.定义一个结构体类型
#include <stdio.h>
#include <string.h>
struct Student {
int id;
char name[50];
float score;
};
2.函数通过指针参数初始化结构体
void init_student(struct Student *stu, int id, const char *name, float score) {
if (stu != NULL) { // 检查指针是否有效
stu->id = id;
strncpy(stu->name, name, sizeof(stu->name) - 1);
stu->name[sizeof(stu->name) - 1] = '\0'; // 确保字符串结束
stu->score = score;
}
}
3.另一个函数,用于打印学生信息,同样使用指针参数避免拷贝
void print_student(const struct Student *stu) {
if (stu != NULL) {
printf("Student ID: %d\n", stu->id);
printf("Name: %s\n", stu->name);
printf("Score: %.2f\n", stu->score);
}
}
4.通过指针参数更新结构体内容
void update_score(Student* stu, float new_score) {
if (stu != NULL) {
stu->score = new_score;
}
}
5.返回结构体指针的函数
Student* create_student(int id, const char* name, float score) {
// 动态分配内存
Student* new_stu = (Student*)malloc(sizeof(Student));
if (new_stu != NULL) {
new_stu->id = id;
strncpy(new_stu->name, name, sizeof(new_stu->name) - 1);
new_stu->name[sizeof(new_stu->name) - 1] = '\0';
new_stu->score = score;
}
return new_stu; // 返回指针
}
6.返回静态结构体指针
Student* get_default_student() {
static Student default_stu; // 静态存储期
default_stu.id = 0;
strcpy(default_stu.name, "Default");
default_stu.score = 60.0f;
return &default_stu; // 返回静态变量地址
}
主函数内,
int main() {
// 方式1: 通过指针参数修改
Student s1;
init_student(&s1, 101, "Alice", 92.5f);
printf("Student 1: %d, %s, %.1f\n", s1.id, s1.name, s1.score);
update_score(&s1, 95.0f);
printf("Updated Score: %.1f\n", s1.score);
// 方式2: 返回动态分配的指针
Student* s2 = create_student(102, "Bob", 85.5f);
if (s2 != NULL) {
printf("Student 2: %d, %s, %.1f\n", s2->id, s2->name, s2->score);
// 修改动态分配的结构体
update_score(s2, 88.0f);
printf("Updated Score: %.1f\n", s2->score);
free(s2); // 必须释放内存
}
// 方式3: 返回静态变量指针
Student* s3 = get_default_student();
printf("Default Student: %d, %s, %.1f\n", s3->id, s3->name, s3->score);
// 修改静态结构体(影响所有调用者)
s3->score = 65.0f;
Student* s4 = get_default_student();
printf("Modified Default: %.1f\n", s4->score); // 输出65.0
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 1. 定义结构体类型
typedef struct {
int id;
char name[50];
float score;
} Student;
// 2. 通过指针参数修改结构体
void init_student(Student *stu, int id, const char *name, float score) {
if (stu != NULL) {
stu->id = id;
strncpy(stu->name, name, sizeof(stu->name) - 1);
stu->name[sizeof(stu->name) - 1] = '\0'; // 确保字符串终止
stu->score = score;
}
}
// 3. 通过指针参数更新结构体内容
void update_score(Student *stu, float new_score) {
if (stu != NULL) {
stu->score = new_score;
}
}
// 4. 返回结构体指针的函数
Student* create_student(int id, const char *name, float score) {
// 动态分配内存
Student *new_stu = (Student*)malloc(sizeof(Student));
if (new_stu != NULL) {
new_stu->id = id;
strncpy(new_stu->name, name, sizeof(new_stu->name) - 1);
new_stu->name[sizeof(new_stu->name) - 1] = '\0';
new_stu->score = score;
}
return new_stu; // 返回指针
}
Student* get_default_student() {
static Student default_stu; // 静态存储期
default_stu.id = 0;
strcpy(default_stu.name, "Default");
default_stu.score = 60.0f;
return &default_stu; // 返回静态变量地址
}
int main() {
// ======================
// 方式1: 通过指针参数修改
// ======================
Student s1;
init_student(&s1, 101, "Alice", 92.5f);
printf("Student 1: %d, %s, %.1f\n", s1.id, s1.name, s1.score);
update_score(&s1, 95.0f);
printf("Updated Score: %.1f\n", s1.score);
// ======================
// 方式2: 返回动态分配的指针
// ======================
Student *s2 = create_student(102, "Bob", 85.5f);
if (s2 != NULL) {
printf("Student 2: %d, %s, %.1f\n", s2->id, s2->name, s2->score);
// 修改动态分配的结构体
update_score(s2, 88.0f);
printf("Updated Score: %.1f\n", s2->score);
free(s2); // 必须释放内存
}
// ======================
// 方式3: 返回静态变量指针
// ======================
Student *s3 = get_default_student();
printf("Default Student: %d, %s, %.1f\n", s3->id, s3->name, s3->score);
// 修改静态结构体(影响所有调用者)
s3->score = 65.0f;
Student *s4 = get_default_student();
printf("Modified Default: %.1f\n", s4->score); // 输出65.0
return 0;
}
结果