温度转换——(基础语法 & 数据类型)
来源:力扣(LeetCode)题源链接.
题目:给你一个四舍五入到两位小数的非负浮点数 celsius 来表示温度,以 摄氏度(Celsius)为单位。
你需要将摄氏度转换为 开氏度(Kelvin)和 华氏度(Fahrenheit),并以数组 ans = [kelvin, fahrenheit] 的形式返回结果。
返回数组 ans 。与实际答案误差不超过 10-5 的会视为正确答案。
开氏度 = 摄氏度 + 273.15
华氏度 = 摄氏度 * 1.80 + 32.00
尝试:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
double* convertTemperature(double celsius, int* returnSize) {
double ans[2]={0};
ans[0] = celsius + 273.15;
ans[1] = celsius * 1.8 + 32;
return ans;
}
测试未通过
这里有两个错误:
1、函数返回一个局部变量ans
报错:runtime error: load of null pointer of type ‘double’ [__ Serializer__.c]
需要知道,函数内定义的局部变量存放在栈(stack)上,在函数结束时将自动回收。当 convertTemperature 函数执行完毕后,局部变量 ans 的生命周期结束,它所占用的内存会被释放,因此返回的指针会变为悬挂指针,指向的内存可能已经被重新分配给其他用途,从而导致未定义行为,比如程序崩溃、数据损坏等。
简单来说,函数运行完之后局部变量ans数组就无效了,此时return ans会是一个错误的值。
还需知道,分配动态内存的变量存放在堆(heap)上,不会像栈上的变量随着函数的执行结束而释放,因此可以使用动态内存分配ans数组内存。
注意到,在程序一开始leetcode有提示,告诉我们需要用malloced来为数组ans分配动态内存,并且假设调用该convertTemperature()函数的调用者会free()
The returned array must be malloced, assume caller calls free().
也就是我们设计该函数时只需要分配动态内存给ans数组就好了,释放内存就交给别人考虑吧!
2、returnSize在函数内未定义
错误:输出结果为[ ]
其实这不算真正的代码错误,只是未符合leetcode设计的要求。
returnSize 参数的常见作用是用来告知调用者返回数组(或动态数组、指针指向的数组等)的实际元素个数。由于C语言本身不直接支持返回数组(只能返回指向数组的指针),无法直接通过返回值获取数组的长度信息,因此需要额外的机制来传递这个信息。
当你编写一个函数,该函数内部生成一个动态大小的数组并想通过指针返回时,除了返回指向数组的指针之外,还需要一种方式来传达这个数组到底有多大。这时,通过传入一个指向整型变量(通常是 int* 类型)的指针作为参数,在函数内部修改这个整型变量的值,就可以达到传递数组长度的目的。
官方解析:
double* convertTemperature(double celsius, int* returnSize) {
double *res = (double *)malloc(sizeof(double) * 2);
res[0] = celsius + 273.15;
res[1] = celsius * 1.80 + 32.00;
*returnSize = 2;
return res;
}
其实看完解析我还是不理解*returnSize到底在哪里发挥作用,*returnSize的值不正确的话,测试也无法通过。
通过揣测官方的题设和通过规则,我猜测代码原型大概是这样子的:
#include <stdio.h>
#include <stdlib.h>
double* convertTemperature(double celsius, int* returnSize) {
*returnSize = 2;
double* ans = (double*)malloc(2 * sizeof(double));
if(ans == NULL) {
perror("Memory allocation failed");// 处理内存分配失败的情况
exit(EXIT_FAILURE);
}
ans[0] = celsius + 273.15;
ans[1] = celsius * 1.8 + 32;
return ans;
}
int main() {
int size = 0;
double* pp = convertTemperature(36.50, &size);
printf("[");
for(int i=0;i<size;i++)
{
printf("%lf", pp[i]); // 打印结果
if(size>0) printf(",");
}
printf("]");
free(pp); // 释放动态分配的内存
return 0;
}
题外:我还发现,该题用static代替malloc的方法也可以通过,即将
double* ans = (double*)malloc(2 * sizeof(double));
替换成
static double ans[2]={0};
嘿嘿,这算不算一个漏洞呢?