6

Why the compiler gives me the error "too many arguments for format" when I use the specifier F in CodeBlocks?

#include <stdio.h>

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

The errors:

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

error: too many arguments for format [-Werror=format-extra-args]
anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • 1
    What compiler does CodeBlocks use? Can you specify the standard? Can you get an update? The uppercase `%F` format specifier was introduced in the C99 standard, so you'll need a compiler that's less than 20 years old. – Adrian Mole Jun 07 '20 at 09:29
  • 2
    @AdrianMole compiler can be new - but it depends on the command line options and/or the default C standard used (you can set it when you build the compiler) – 0___________ Jun 07 '20 at 09:30

3 Answers3

4

Looks like some versions of GCC don't recognize %F, oddly enough. My gcc version 9.2.0 (tdm64-1) for windows with C11 standard, does not recognize it though it only issues those as warning messages not errors.

$ 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);
      |            ^~~~~~

Upon execution the value is not printed.

I'm guessing you might be using some mingW installation in a Windows system and your compiler must be treating warnings as errors, which is not a bad idea.

As @HolyBlackCat suggested, adding -D__USE_MINGW_ANSI_STDIO flag solves the issue.

This thread has the instructions on how to do it.

@RobertS supports Monica Cellio answer has a link with instructions on how to add it to CodeBlocks.

Alternatively, for a quick fix of the code you can use %G, or %E for scientific notation.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • 2
    GCC 10.1 from MSYS2, no warnings. Does adding `-D__USE_MINGW_ANSI_STDIO` change anything for you? – HolyBlackCat Jun 07 '20 at 10:06
  • @anastaciu yes i installed minGW...have i to copy and paste the first line of your code in codeblocks to catch more informations about the errors? – Federica Guidotti Jun 07 '20 at 10:12
  • 1
    @FedericaGuidotti, I used [@HolyBlackCat comment](https://stackoverflow.com/questions/62243319/printff-x-ok-printff-x-error-too-many-arguments-for-format/62243694?noredirect=1#comment110083072_62243694) to solve the issue, try that, I added it to my answer. – anastaciu Jun 07 '20 at 10:15
  • 1
    @anastaciu This flag is described [here](https://stackoverflow.com/questions/44382862/how-to-printf-a-size-t-without-warning-in-mingw-w64-gcc-7-1), I think I'll just leave a link to that thread instead of posting a full answer. – HolyBlackCat Jun 07 '20 at 10:15
  • @FedericaGuidotti The first line of his example is the compiler invocation. It does not work if you paste this line inside of the code itself. You need to setup the compiler invocation and the compiler options in CodeBlocks. – RobertS supports Monica Cellio Jun 07 '20 at 10:16
2

The F format specifier was first introduced in C99. Your compiler either seems to be compliant to C89/C90 or the std=c90/std=c89 compiler option is enabled.

If you configured compiler is gcc, you can use the gcc --version command to detect the version.

Else you should check the set compiler options for which standard the compiler uses. Take a look at here:

How to add compiler flags on codeblocks

Although for Ubuntu (I don´t know on what OS you are using CodeBlocks), but this answer gives you an visual overview of the set up for compiler options in CodeBlocks.

2

The compiler gives you the error "too many parameters for printf" because it doesn't recognize %F as a format specifier.... so the parameter you have added to printf() is extra, and should not be there.

The standard format specifiers from C89 below, specify that the floating point formats are e, E, f, g and G (does not include F, the reason is stated in the last edit of this answer)

Remember that the compiler shouldn't read the format string of printf() at all to match the parameters with the format specifiers, so what is happening there should only deal with the printf(3) specification, and that is indeed an issue for printf(3) not for the compiler. Probably if you try the generated program it should work.

EDIT

I have tried on clang (sorry, but I have no gcc here) and I have discovered some possible cause of the issue (not an error, either). The printf(3) implementation here, does never switch to scientific notation at all (which is something I have not checked with the standard) so it is never going to generate an alphabetic character and no lowercase or uppercase letter is concerned. So for the program

#include <stdio.h>

int main()
{
        printf("%5.3G\n", 3.141592654E160);
}

it prints:

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

while for

#include <stdio.h>

int main()
{
        printf("%5.3F\n", 3.141592654E160);
}

it prints

$ a.out
31415926539999999255132844331312943389972993386142531366742209094398699375217155068328829400434148008839629239544769533043070670437328460352417427610347451187200.000
$ _

As only digits and decimal point are emitted, there's no uppercase or lowercase interpretation on the case of the format specifier, making both forms equivalent (but one being nonstandard).

The solution is just to switch to lowercase f.

As @chux-ReinstateMonica suggests in one of the comments, C89, page 133 (143 of the pdf), the standard doesn't include the F format specifier, only e, E, f, g and G. This should be normal, considering that f never changes to exponential notation.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31
  • "doesn't accept the %F specifier, which is rare." --> A C89 compiler may not recognize it. – chux - Reinstate Monica Jun 08 '20 at 20:14
  • The problem is that I have clang here, I cannot test. The good news is that the format specifier is not something that has to do with the compiler... but with the implementation internals of `printf(3)` which is part of the standard c library, with shouldn't be interfered by the compiler's opinion. :) – Luis Colorado Jun 08 '20 at 20:20
  • [C89](https://www.pdf-archive.com/2014/10/02/ansi-iso-9899-1990-1/ansi-iso-9899-1990-1.pdf), page 133 does not list `F` as a `printf` specifier. A compliant C89 compiler, sadly still used these days, leads to UB with the invalid specifier `'F'`. – chux - Reinstate Monica Jun 08 '20 at 20:24
  • See my edit to the question. `F` doesn't ever swith to exponential notation, so there's no sense in considering lower or uppercase in the case of `F`. Just having `f` should suffice. clang doesn't emit a warning, and freebsd library implements it... but you shouldn't use it, as you have checked. – Luis Colorado Jun 08 '20 at 20:34
  • Agree about exponential notation, yet `F` vs `f` since C99 does affect the case of `inf, infinity, nan`. Unclear what C89 specifies with those. – chux - Reinstate Monica Jun 08 '20 at 20:47
  • Have you checked that? – Luis Colorado Jun 08 '20 at 20:51
  • `printf("%f %F\n", 1.0/0.0, 1.0/0.0);` prints `inf INF` for me. What does that print for you? – chux - Reinstate Monica Jun 08 '20 at 20:54
  • It works also for me... you are right... but it's not standard... its a feature. Gcc is free to notice that (think that it's only a warning). CLANG doesn't emit such a warning. – Luis Colorado Jun 08 '20 at 20:55
  • Unclear about your "but it's not standard". Since C99 it is standard specification to use upper, lower case per `'F'`, `'f'`. "The F conversion specifier produces INF, INFINITY, or NAN instead of inf, infinity, or nan, respectively" – chux - Reinstate Monica Jun 08 '20 at 21:01
  • It's not clear also for me. You just showed to me a C89 version of the standard that hadn't it. In that standard the thing is not included... Have you another standard edition where it appears? If you have it in an ulterior edition, then it will be standard. My "being standard" idea is, as everyone I think, if it is documented in the standard document. An extension, on the contrary is something a compliant compiler implements, but not following the standard directrices, while those directrices allow, or don't say a word in contrary to implement such a thing. Of course, C89 is too old now – Luis Colorado Jun 09 '20 at 13:09
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/215594/discussion-between-chux-reinstate-monica-and-luis-colorado). – chux - Reinstate Monica Jun 09 '20 at 14:31