在C语言中将double转换为char*

3

如何将双精度浮点数转换为 char*。

#include <stdio.h>

int main() {
    char * buf;
    double number = 3.123;
    sprintf(buf,"%f",number);
    printf("%s",buf);
    return 0;
}

这个方法无法工作,我不知道原因。

2个回答

5

char* buf声明buf为字符指针,但并未实际分配内存。您应该将buf声明为数组以分配内存:

char buf[128];
double number = 3.123;
sprintf(buf, "%f", number);

1
您可能需要的是浮点数转换为字符串。您需要的不是一个char*,而是一个数组。区别在于数组为字符串分配了一些空间,而指针则应该指向已经存在的字符串,但是在您的代码中并没有这样的字符串。
因此,您的代码会产生未定义行为(或简称UB),因为sprintf()试图写入buf指针引用的地址。指针未被分配指向任何内容,因此它是未初始化的(野指针)。该指针可能包含随机无意义的值,并且sprintf()正在尝试将其写入-这不起作用,甚至更糟糕的是,它会出现工作正常,直到您在完全不同的代码部分发现问题。
以下是正确的做法:
#include <stdio.h>

int main(void)
{
    char buf[100];
    double number = 3.123;
    sprintf(buf, "%f", number);
    printf("%s", buf);
}

首先,我们声明一个字符数组。它可以是任意长度,但为了简单起见,我选择了100。我们可以通过使用sprintf()来类似地写入该数组。
现在,可能会出现另一个问题。在这个小代码片段中不会显示出来,但如果你经常使用sprintf(),如果不注意数组的长度,你会注意到很多错误。数组只有100个字符,但sprintf()并不知道!该函数将尝试简单地写入超出数组末尾的位置,这是一种称为缓冲区溢出的错误,另一种未定义行为(UB)的情况,也是恶意攻击的一个非常普遍的漏洞。
为了使程序员的生活更轻松,C还有另一个更安全的函数snprintf(),它基本上与sprintf()相同,但需要一个额外的参数,即数组的最大长度。以下是其工作原理:
#include <stdio.h>

int main(void)
{
    char buf[100];
    double number = 3.123;
    snprintf(buf, 100, "%f", number);
    printf("%s", buf);
}

即使我们试图向缓冲区写入超过100个字符,该函数也只会写入100个字符(实际上是99个字符和一个空终止符),并且会丢弃其余的内容。这意味着,如果您传递正确的数组长度值,就不会发生缓冲区溢出。

需要注意的是,snprintf 是非标准的,而且 %f 格式化字符串本来就不应该超过 100 个字符。 - Aplet123
1
需要注意的是,snprintf()非常标准(C99: 7.19.6.5,C11: 7.21.6.5)。实际上,我说过OP发布的这个小代码片段不会导致缓冲区溢出,但我想让他知道这个函数,因为它要好得多。需要键入额外参数的需求提醒您需要小心长度。 - DarkAtom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接