void函数指针问题致C程序输出-nan:海伦公式求三角形面积故障排查
问题分析与修复方案
核心问题点
- 输入格式不匹配:你的
scanf用了"%lf, %lf, %lf",要求输入必须是逗号分隔的三个数(比如3,4,5),但你只输入了单个5,导致变量b、c未被初始化,内存里是随机垃圾值,后续计算直接出错。 - 指针参数冲突:调用
heron(&result, a, b, c, &result)时,把同一个变量的地址同时传给semiPerimeter和result指针。函数执行时,先读取*semiPerimeter(原半周长),但随后会把计算结果覆盖到同一个地址,直接毁掉了半周长的值——虽然这不是这次-nan的直接原因,但属于严重逻辑漏洞。 - 无合法性校验:海伦公式要求三边必须能构成三角形(任意两边之和大于第三边),且
s*(s-a)*(s-b)*(s-c)必须非负,否则sqrt会返回nan。
修复后的完整代码
#include <math.h> #include <stdlib.h> #include <stdio.h> void CalculateSemiPerimeter(double a, double b, double c, double *result) { *result = (a + b + c) / 2.0; } // 优化:直接传半周长的值,避免指针冲突 void heron(double semiPerimeter, double a, double b, double c, double *result) { double sub1 = semiPerimeter - a; double sub2 = semiPerimeter - b; double sub3 = semiPerimeter - c; *result = semiPerimeter * sub1 * sub2 * sub3; } int main() { double a, b, c, semi, area_sq; // 修改输入格式为空格分隔,更符合常规输入习惯 printf("输入三角形三边(空格分隔):"); // 校验输入是否有效 if (scanf("%lf %lf %lf", &a, &b, &c) != 3) { printf("输入错误,请输入三个数字!\n"); return 1; } // 校验三边是否能构成有效三角形 if (a <= 0 || b <= 0 || c <= 0 || a + b <= c || a + c <= b || b + c <= a) { printf("输入的三边无法构成有效三角形!\n"); return 1; } CalculateSemiPerimeter(a, b, c, &semi); heron(semi, a, b, c, &area_sq); // 极端情况校验:防止乘积为负 if (area_sq < 0) { printf("计算异常,乘积为负!\n"); return 1; } double area = sqrt(area_sq); printf("三角形面积:%.2lf\n", area); return 0; }
关键修复说明
- 输入逻辑修正:把
scanf格式改为"%lf %lf %lf",支持空格分隔的输入(比如3 4 5),同时增加输入计数校验,确保三个边都被正确读取。 - 解决指针冲突:将
heron函数的第一个参数从指针改为普通double类型,直接传递半周长的值,避免同一个内存地址被同时读写的问题,代码逻辑更清晰。 - 合法性校验:新增三边正数检查和三角形三边关系校验,从源头杜绝无效计算。
- 容错处理:增加对海伦公式乘积的非负校验,防止极端情况下
sqrt返回nan。
内容的提问来源于stack exchange,提问作者HaveMercy
相关产品推荐
相关产品推荐

