【问题标题】:printf("%f",x) ok, printf("%F",x) error too many arguments for formatprintf("%f",x) ok, printf("%F",x) error too many arguments for format
【发布时间】:2020-09-26 07:28:55
【问题描述】:

当我在 CodeBlocks 中使用说明符 F 时,为什么编译器会给出错误“格式参数过多”?

#include <stdio.h>

int main()
{
    float x = 3.14159;
    printf("%f\n", x);
    printf("%F\n", x);
    return 0;
}

错误:

error: unknown conversion type character 'F' in format [-Werror=format=]

error: too many arguments for format [-Werror=format-extra-args]

【问题讨论】:

  • CodeBlocks 使用什么编译器?可以指定标准吗?你能得到更新吗?大写的 %F 格式说明符是在 C99 标准中引入的,因此您需要一个不到 20 年的编译器。
  • @AdrianMole 编译器可以是新的 - 但它取决于命令行选项和/或使用的默认 C 标准(您可以在构建编译器时设置它)

标签: c printf codeblocks format-specifiers


【解决方案1】:

看起来有些版本的 GCC 无法识别 %F,这很奇怪。我的gcc version 9.2.0 (tdm64-1) 用于具有 C11 标准的 windows,虽然它只发出警告消息而不是错误消息,但无法识别它。

$ gcc main2.c -Wextra -Wall -pedantic -std=c11
main2.c: In function 'main':
main2.c:7:14: warning: unknown conversion type character 'F' in format [-Wformat=]
    7 |     printf("%F\n", x);
      |              ^
main2.c:7:12: warning: too many arguments for format [-Wformat-extra-args]
    7 |     printf("%F\n", x);
      |            ^~~~~~

执行时不打印该值。

我猜您可能在 Windows 系统中使用了一些 mingW 安装,并且您的编译器必须将警告视为错误,这不是一个坏主意。

作为@HolyBlackCat suggested,添加-D__USE_MINGW_ANSI_STDIO 标志可以解决问题。

This thread 有操作说明。

@RobertS supports Monica Cellio answer 有一个链接,其中包含有关如何将其添加到 CodeBlocks 的说明。

或者,要快速修复代码,您可以使用%G%E 作为科学记数法。

【讨论】:

  • 来自 MSYS2 的 GCC 10.1,没有警告。添加-D__USE_MINGW_ANSI_STDIO 对您有什么改变吗?
  • @anastaciu 是的,我安装了 minGW...让我复制并粘贴代码块中的第一行代码以获取有关错误的更多信息?
  • @FedericaGuidotti,我用@HolyBlackCat comment 解决了这个问题,试试吧,我把它添加到我的答案中。
  • @anastaciu 这个标志被描述为here,我想我会留下一个链接到那个线程而不是发布完整的答案。
  • @FedericaGuidotti 他的示例的第一行是编译器调用。如果您将此行粘贴到代码本身内,它将不起作用。您需要在 CodeBlocks 中设置编译器调用和编译器选项。
【解决方案2】:

F 格式说明符最初是在 C99 中引入的。您的编译器似乎与 C89/C90 兼容,或者启用了 std=c90/std=c89 编译器选项。

如果你配置的编译器是gcc,可以使用gcc --version命令检测版本。

否则,您应该检查编译器使用的标准的设置编译器选项。看看这里:

How to add compiler flags on codeblocks

虽然对于 Ubuntu(我不知道您在什么操作系统上使用 CodeBlocks),但this 的回答为您提供了 CodeBlocks 中编译器选项设置的直观概览。

【讨论】:

    【解决方案3】:

    编译器给你错误“printf 的参数太多”,因为它不能将 %F 识别为格式说明符......所以你添加到 printf() 的参数是 extra em>,不应该在那里。

    来自下面C89的标准格式说明符,指定浮点格式为eEfgG(不包括F,原因是在此答案的最后一次编辑中说明)

    请记住,编译器根本不应该读取 printf() 的格式字符串来将参数与格式说明符匹配,所以那里发生的情况应该只处理 printf(3) 规范,这确实是printf(3) 的问题,而不是编译器的问题。如果您尝试生成的程序,它应该可以工作。

    编辑

    我已经尝试过 clang(抱歉,我这里没有 gcc)并且我发现了一些可能的问题原因(也不是错误)。 printf(3) 这里的实现,根本不会切换到科学记数法(这是我没有用标准检查过的东西),所以它永远不会生成字母字符,也不关心小写或大写字母。所以对于程序

    #include <stdio.h>
    
    int main()
    {
            printf("%5.3G\n", 3.141592654E160);
    }
    

    打印出来:

    $ ./a.out
    3.14E+160
    $ _
    

    #include <stdio.h>
    
    int main()
    {
            printf("%5.3F\n", 3.141592654E160);
    }
    

    打印出来

    $ a.out
    31415926539999999255132844331312943389972993386142531366742209094398699375217155068328829400434148008839629239544769533043070670437328460352417427610347451187200.000
    $ _
    

    由于仅发出数字和小数点,因此格式说明符的大小写没有大写或小写解释,使两种形式等效(但一种是非标准形式)。

    解决办法就是改成小写f

    正如@chux-ReinstateMonica 在其中一个 cmets 中所建议的那样,C89,第 133 页(pdf 的 143 页),该标准不包括 F 格式说明符,只有 eEfgG。这应该是正常的,考虑到f 永远不会更改为指数符号。

    【讨论】:

    • "不接受 %F 说明符,这种情况很少见。" --> C89 编译器可能无法识别它。
    • 问题是我这里有clang,我无法测试。好消息是格式说明符与编译器无关……而是与标准 c 库的一部分 printf(3) 的实现内部有关,编译器的意见不应干扰。 :)
    • C89,第 133 页未将 F 列为 printf 说明符。可悲的是,如今仍在使用的兼容 C89 编译器会导致带有无效说明符 'F' 的 UB。
    • 查看我对问题的编辑。 F 永远不会转换为指数符号,因此在 F 的情况下考虑小写或大写是没有意义的。只需拥有f 就足够了。 clang 不会发出警告,freebsd 库实现了它......但你不应该使用它,因为你已经检查过。
    • 同意指数符号,但F vs f 因为C99 确实影响inf, infinity, nan 的大小写。不清楚 C89 对这些的规定。
    猜你喜欢
    • 1970-01-01
    • 2022-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 2011-01-17
    相关资源
    最近更新 更多