如何使用 C 的 sprintf() 安全地格式化浮点数/双精度数?

发布于 2024-10-01 05:02:53 字数 971 浏览 1 评论 0原文

我正在将我的一个 C++ 库移植到一个有点奇怪的编译器 - 它不支持字符串流,也不支持 snprintf() 等 C99 功能。我需要将 intfloat 等值格式化为 char*,唯一可用的选项似乎是 1)使用 sprintf ()2)手卷格式化程序。

鉴于此,我如何确定(在编译时或运行时)格式化浮点值需要多少字节?我的库可能用于模糊测试,因此它需要处理异常或极端值。

或者,是否有一个小型(首选 100-200 行)、可移植的 snprintf() 实现,我可以简单地将其与我的库捆绑在一起?

理想情况下,我最终会得到基于正常 snprintf() 的代码,或者类似的代码:

static const size_t FLOAT_BUFFER_SIZE = /* calculate max buffer somehow */;

char *fmt_double(double x)
{
    char *buf = new char[FLOAT_BUFFER_SIZE + 1];
    sprintf(buf, "%f", x);
    return buf;
}

相关问题:

I'm porting one of my C++ libraries to a somewhat wonky compiler -- it doesn't support stringstreams, or C99 features like snprintf(). I need to format int, float, etc values as char*, and the only options available seem to be 1) use sprintf() 2) hand-roll formatting procedures.

Given this, how do I determine (at either compile- or run-time) how many bytes are required for a formatted floating-point value? My library might be used for fuzz-testing, so it needs to handle even unusual or extreme values.

Alternatively, is there a small (100-200 lines preferred), portable implementation of snprintf() available that I could simply bundle with my library?

Ideally, I would end up with either normal snprintf()-based code, or something like this:

static const size_t FLOAT_BUFFER_SIZE = /* calculate max buffer somehow */;

char *fmt_double(double x)
{
    char *buf = new char[FLOAT_BUFFER_SIZE + 1];
    sprintf(buf, "%f", x);
    return buf;
}

Related questions:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光无声 2024-10-08 05:02:53

编译器是否支持 ecvtfcvtgcvt 中的任何一个?它们有点怪异,并且很难使用,但是它们有自己的缓冲区(ecvtfcvt)和/或者您可能会幸运地发现系统标头具有,与 VC++ 中一样,定义了 gcvt 将生成的最大字符数。你可以从那里拿走它。

如果做不到这一点,我认为按照提供的代码行,以下内容是完全可以接受的。对于 double 来说 500 个字符相当保守;有效值大约为 10^-308 到 10^308,因此即使通过打印出所有数字来确定实现很烦人,也不应该出现溢出。

char *fmt_double(double d) {
    static char buf[500];
    sprintf(buf,"%f",d);
    assert(buf[sizeof buf-1]==0);//if this fails, increase buffer size!
    return strdup(buf);
}

这并不能提供任何惊人的保证,但它应该是相当安全的(tm)。不幸的是,我认为这种方法已经达到了最好的效果。但是,如果您有定期运行调试版本的习惯,那么您至少应该得到任何问题的早期警告......

Does the compiler support any of ecvt, fcvt or gcvt? They are a bit freakish, and hard to use, but they have their own buffer (ecvt, fcvt) and/or you may get lucky and find the system headers have, as in VC++, a definition of the maximum number of chars gcvt will produce. And you can take it from there.

Failing that, I'd consider the following quite acceptable, along the lines of the code provided. 500 chars is pretty conservative for a double; valid values are roughly 10^-308 to 10^308, so even if the implementation is determined to be annoying by printing out all the digits there should be no overflow.

char *fmt_double(double d) {
    static char buf[500];
    sprintf(buf,"%f",d);
    assert(buf[sizeof buf-1]==0);//if this fails, increase buffer size!
    return strdup(buf);
}

This doesn't exactly provide any amazing guarantees, but it should be pretty safe(tm). I think that's as good as it gets with this sort of approach, unfortunately. But if you're in the habit of regularly running debug builds, you should at least get early warning of any problems...

你列表最软的妹 2024-10-08 05:02:53

我认为 GNU Libiberty 就是你想要的。您可以只包含 snprintf 的实现。

vasprintf.c - 152 LOC。

I think GNU Libiberty is what you want. You can just include the implementation of snprintf.

vasprintf.c - 152 LOC.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文