我有一些使用 strtod(...) 将 ASCII 字符串转换为双精度的 C 代码。该程序已针对 x86(调试)、ARM 和 PowerPC(嵌入式目标系统)进行编译。ARM 板实际上是一个运行 Debian 的 BeagleBoard xM,可用于它。
我发现 strtod() 不能在 ARM / Debian 系统上正确转换值。事实上,我尝试的所有值都是 0.000。
为了演示,我编写了以下非常简单的测试程序:
#include <stdio.h>
#include <stdlib.h>
int main(const int argc, const char **argv)
{
const char myString[] = "123 ";
char *myEnd1 = NULL;
char *myEnd2 = NULL;
float fValue = 0;
double dValue = 0;
dValue = atof(myString);
printf( "Using atof():\n"
" String: %s\n"
" Double: %lf\n",
myString,
dValue );
fValue = strtof(myString, &myEnd1);
dValue = strtod(myString, &myEnd2);
printf( "Using strtof() / strtod():\n"
" String: %s\n"
" Float: %f (%d)\n"
" Double: %lf (%d)\n",
myString,
fValue, (myEnd1 - myString),
dValue, (myEnd2 - myString) );
return 0;
}
所有这些都是在运行 Ubuntu 的 x86 PC 上编译的(实际上是在虚拟机中)。我有用于 PowerPC 和 ARM 编译的交叉编译器工具链。
在 x86 和 PowerPC 系统上,输出符合预期,即:
Using atof():
String: 123
Double: 123.000000
Using strtof() / strtod():
String: 123
Float: 123.000000 (3)
Double: 123.000000 (3)
然而,当在 BeagleBoard 上运行时,我得到了这个:
Using atof():
String: 123
Double: 0.000000
Using strtof() / strtod():
String: 123
Float: -0.372039 (3)
Double: 0.000000 (3)
啊???我错过了什么愚蠢的事情吗?请注意,“myEnd”指针只是用来显示 strtod() 和 strtof() 确实找到了第一个非数字字符,因此找到了数字的结尾。他们在两种情况下都报告了数字中正确的字符数(3),但转换后的值是错误的。我不认为这是一个语言环境问题,因为没有小数点可以混淆。
编辑:
我刚刚使用“-static”选项重新编译了测试程序。当然,这使二进制文件变得更大,但现在它可以在目标 ARM 平台上正常工作。
我对图书馆的工作方式有点模糊。另外,我不记得我是如何构建我的交叉编译器工具链的。它可能不是从与实际安装在目标板上的 Debian Linux 相同的源构建的。
那么,atof() 等莫名其妙的行为是否意味着动态链接的可执行文件“预期”的库与系统上的实际库不同?我很惊讶这并没有导致更严重的问题。我们已经运行这个系统一年了,到目前为止,这是我们遇到的唯一一个奇怪的错误。