栈上初始化
本课属于 Coddy C 学习旅程的“面向对象编程”单元。第 14 课,共 61 课。
并非每个对象都需要放在堆上。当结构体很小且生命周期很短时,在栈上分配它更简单、更快:不需要 malloc,不需要 free,也没有内存泄漏的风险。
工厂函数也可以按值返回结构体,而不是返回指针。整个结构体都会被复制到调用方:
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p;
p.x = x;
p.y = y;
return p;
}
调用者会收到一个完全初始化的副本:
Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);
没有指针,也不需要清理。当 origin 和 cursor 超出作用域时,它们会自动销毁。
这种方法最适合不含动态分配成员的小型结构体。对于较大的对象或包含指向堆内存的指针的对象,使用 malloc 的构造函数模式仍然是更好的选择。
挑战
简单让我们使用工厂函数构建一个 Temperature 模块,在栈上创建温度读数。与之前课程中基于堆的构造函数不同,这种方式按值返回结构体:不需要 malloc,不需要 free,只需简单高效地在栈上分配。
你需要创建三个文件:
temperature.h:声明一个Temperature结构体,包含两个成员:double celsius和char scale(用于存储摄氏温度标记 'C')。另外,还要声明两个函数:create_temperature:接收一个 double 值,并按值返回一个Temperature结构体(不是指针!)temperature_to_fahrenheit:接收一个const Temperature *,并以 double 类型返回对应的华氏温度
TEMPERATURE_H设置包含保护。temperature.c:实现这两个函数。工厂函数应创建一个局部Temperature变量,初始化它的字段(将scale设置为'C'),并返回该变量。转换公式为:fahrenheit = celsius * 9.0 / 5.0 + 32.0main.c:使用工厂函数创建温度读数,并显示摄氏温度和华氏温度。
你会收到一个输入:摄氏温度(double 类型)。
在主文件中,使用 create_temperature,根据给定值创建一个 Temperature 结构体。然后打印原始摄氏温度值及其对应的华氏温度值。
请按以下格式输出:
Celsius: {celsius}
Fahrenheit: {fahrenheit}两个值都使用 %.2f,显示两位小数。
例如,输入 25.0 时,输出为:
Celsius: 25.00
Fahrenheit: 77.00请注意,这种方式非常简洁。你会得到一个完全初始化的结构体,无需担心内存管理。当 Temperature 变量超出作用域时,它会自动清理。
亲手试试
#include <stdio.h>
#include "temperature.h"
int main() {
double celsius_input;
scanf("%lf", &celsius_input);
// TODO: 使用 create_temperature 创建一个 Temperature 结构体
// TODO: 使用 %.2f 格式打印摄氏温度值
// TODO: 使用 temperature_to_fahrenheit 转换并打印华氏温度值
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C 在线编译器