案例一
先来看一个案例:
int main()
{
int n = 0;
float x = -123.456f;
float y = fabs(x);
while(1)
{
y = y + 1;
n++;
}
}
调试环境:
KEIL_MDK V4.72
你觉得执行完“float y = fabs(x);”这一行之后,y的值等于多少?是123.456吗?
执行结果
先看看代码:
再看看编译过程:
似乎没有问题。不就一个编译告警吗?又不是error,先不管它,能生成bin就好。
调试运行一下:
咦,y怎么变得那么大啦?
再看看,
没错啊,y的值就是这么大啊。奇怪了。。。。。。
案例二
在main.c之外,还有一个function模块。
头文件function.h的代码为:
#ifndef FUNCTION_H
#define FUNCTION_H
float GetMaxFloat(float x, float y);
#endif
源文件function.c的代码为:
#include "function.h"
float GetMaxFloat(float x, float y)
{
float z;
if (x > y)
{
z = x;
}
else
{
z = y;
}
return z;
}
在main()函数中增加以下几行代码:
float a = 12.3f;
float b = 45.6f;
float c = GetMaxFloat(a, b);
工程情况如下:
执行完c=GetMaxFloat(a,b);之后,c的值是我们所期望的45.6吗?
来,调试一下看看:
a和b的值都是对的,但c的值错得很离谱啊。
解决对策
包含对应的头文件,消除编译告警!
现在变成这个样子:
注意:增加两行include之后,左边的黄色感叹号也没有了。
再看看运行结果:
现在,y和c的值都对啦!!
原因分析
编译器在没有找到函数声明的时候,会默认为返回int型。
比如,GetMaxFloat()函数,本来它应该是
float GetMaxFloat(float x, float y);
但编译器会当成是
int GetMaxFloat(double x, double y);
看看汇编:
正确的情况
先把12.3f和45.6f加载到s0和s1寄存器。调用GetMaxFloat函数得到计算结果,再保存到s19寄存器。
错误的情况
调用了__aeabi_f2d函数把a和b转换了一下(先变成double型?),再调用GetMaxFloat函数。