如何在不更改格式说明符的情况下同时支持双精度和长双精度?

How do you support both doubles and long doubles without changing format specifiers?

提问人:KJ7LNW 提问时间:10/28/2023 最后编辑:John KugelmanKJ7LNW 更新时间:10/28/2023 访问量:96

问:

我能够通过简单地搜索替换 来使用 's 编译 xnec2c。它计算正确,除非使用格式说明符的任何地方,因为它想要......当然,GCC 在用这句话入侵它之后,正在吠叫很多:long doubledoublelong double%Lf-Wformat=

perl -p -i -e 's/_Complex/complex/g; s/gdouble/double/g; s/([ \t(]|^)double/$1long double/g' src/*.[ch]

最终目标是:

  1. 将所有 替换为doubletypedef double xnec2c_double_t
  2. 提供一个选项,将 typedef 调整为 ../configure --enable-long-doubleconfigure.aclong double
  3. 不破坏 ' 和相关的基于格式说明符的函数(如 等)。printfsprintf

问题:

通过更改 ?doublelong doubletypedef

我可以在每个打印件周围加上 ',或者和字符串连接在一起,但这似乎几乎和在每个 .如果有一种优雅的方法可以做到这一点,宏可能是一种选择,但我还没有想出一个。#ifdef#define SPEC_DOUBLE "%Lf"printf("foo=" SPEC_DOUBLE "\n", foo)#ifdefprintfmy_smart_printf

有没有“好”的方法可以做到这一点?

注意:

  • 我宁愿不切换到 C++。
  • 这个问题与autoconf无关。
  • 我是xnec2c的维护者。
c 浮点 printf 双格式 字符串

评论

3赞 chux - Reinstate Monica 10/28/2023
使用和石膏:Lprintf("%Lf\n", (long double) double_or_long_double_object);
7赞 chux - Reinstate Monica 10/28/2023
就个人而言,我喜欢你的方法。这有什么不好的?虽然要匹配宏,它应该是 .#define SPEC_DOUBLE "%Lf"PRI#define SPEC_DOUBLE "Lf"
2赞 Jonathan Leffler 10/28/2023
我赞同 @chux-ReinstateMonica 的观点:我会为该类型创建一个 typedef,并将该类型的定义作为编译时选择。我还会根据 中使用的方案为 创建一组宏名称和格式。该标准保留了 PRI 或 SCN,后跟小写字母或 X 以备将来使用。如果你有一个标准的项目前缀(我假设它是 PFX),那么我会使用像 and 这样的名称(其中 the 是你为 typedef 发明的名称,减去任何项目前缀)。[...继续...]scanf()printf()<inttypes.h>PFX_PRIG_typedefnamePFX_SCNf_typedefnametypedefname
0赞 Jonathan Leffler 10/28/2023
[...继续...]如果您没有项目前缀,并且不想发明一个前缀,那么 using 接近标准用于整数的内容,但在保留的命名空间中则不然。然后,您可能拥有代码和常规代码。我会利用 和 w.r.t 的对称性在两者中工作,即使对 for 感到满意。PRI_G_typedefname#define PFX_PRIG_typedefname "LG"long double#define PFX_SCNf_typedefname "lf"doubleprintf()scanf()"%lf"doubleprintf()"%f"double
0赞 Craig Estey 10/28/2023
SPEC_DOUBLE是我个人在这种情况下使用的。但是,我也这样做:with:并在需要时使用它,使用诸如代替和(例如)或代替的宏进行调整。然后只有函数必须改变。printf("%s\n",print_double(whatever));const char *print_double(double val) { static char buf[100]; sprintf(buf,"%f",val); return buf; }long doubleSPEC_DOUBLE%ftypedef long double TYPE_DOUBLE;#define TYPE_DOUBLE long doubledouble

答:

2赞 chux - Reinstate Monica 10/28/2023 #1

如何在不更改 C 格式说明符的情况下同时支持双精度和长双精度?

  • 将浮点参数转换为并使用匹配说明符,以便在所有情况下都可以使用相同的格式。long doublelong double

    printf("%Lf\n", (long double) float_or_double_or_long_double_object);
    
  • 按照 中的示例并创建自己的说明符,如 .注意没有。PRI...<inttypes.h>#define SPEC_DOUBLE "Lf""%"

    printf("%" SPEC_DOUBLE "\n", xnec2c_double_object);
    
  • 创建一个帮助程序函数,将特殊浮点转换为字符串

    extern char *xnec2c_to_str(char *dest, xnec2c_double_t x);
    //                     -        digits           .  frac  \0 
    #define xnec2c_STR_SZ (1 + (LDBL_MAX_10_EXP+1) + 1 + 6 + 1)
    #define xnec2c_TO_STR(x) (xnec2c_to_str((char[xnec2c_STR_SZ]){ 0 }, x)
    printf("%s\n", xnec2c_TO_STR(x));
    
  • 现在,对于完全不同的东西,请考虑格式化打印,而无需指定类型匹配说明符