2

The following program results in compiler warnings if the include statement in line 4 is added (uncommented).

Compiler: gcc version 8.1.0 (i686-win32-dwarf-rev0, Built by MinGW-W64 project)

#define __STDC_FORMAT_MACROS

// Adding this and -Wall results in compiler warning
//#include "stdio.h"

#include <cstdint>
#include <cinttypes>
#include <cstdio>

int main()
{
    int64_t i     = 0;
    printf("%" PRId64, i);
}

The warnings are:

testlld.cpp:11:14: warning: unknown conversion type character 'l' in format [-Wformat=]
  std::printf("%" PRId64, i);
              ^
testlld.cpp:11:14: warning: too many arguments for format [-Wformat-extra-args]
testlld.cpp:11:14: warning: unknown conversion type character 'l' in format [-Wformat=]
testlld.cpp:11:14: warning: too many arguments for format [-Wformat-extra-args]

Can someone explain what happens?

I can of course fix this by using only <cstdio>, which would be the correct thing in this case.

But it leads to another question...

Say I have a header file that is included by two implementation files - one compiled with a C compiler and one compiled with a C++ compiler. The header file would need to use "stdio.h" since it needs to compile with a C compiler. Does this mean that all code including that header file must also use "stdio.h" and NOT <cstdio>, even if it is C++ code?

jgreen81
  • 705
  • 1
  • 6
  • 14
  • 1
    See this question to understand differences between cstdio and stdio.h : https://stackoverflow.com/questions/10460250/cstdio-stdio-h-namespace. If you have a header that's shared between C and C++ code, you might want to use #ifdef _cplusplus macro and extern "C" stuff – Pierre Baret Sep 16 '21 at 07:37
  • If you're including a C header in a C++ project you should wrap the whole thing in an `extern "C" { ... }`. You can't just mix them freely, they're different languages. – Useless Sep 16 '21 at 07:39
  • (Aside from your actual problem, I recommend that in C++ you use [`std::cout`](https://en.cppreference.com/w/cpp/io/cout) (defined in `iostream`) instead of the C-style `printf`.) – Aziuth Sep 16 '21 at 08:40
  • @Aziuth Certainly. A lot of challenges could probably be mitigated by iostream. Thanks for suggestion. I was aware already, though. – jgreen81 Sep 16 '21 at 08:41

2 Answers2

1

This seems to be a known bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60434

This makes sense since - despite the warning - the 64 bit integer is printed correctly.

By the way, when compiling as C (changing the included headers to .h), the format string defined by PRId64 is I64d. Using this format string gives no warning neither when compiling as C nor as C++. Hence a possible workaround is to use

    printf("%I64d", i);

Another option is to build with -D__USE_MINGW_ANSI_STDIO.

nielsen
  • 5,641
  • 10
  • 27
  • Is I64d standard? I'm under the impression that it's some kind of VS extension. Maybe some/most compilers support it but I'd like to avoid using non-standard stuff for these kind of things. – jgreen81 Sep 16 '21 at 08:43
  • 2
    No, it is not standard and I do agree with your concern about using it. – nielsen Sep 16 '21 at 08:52
1

Following the suggestions above, I did the following, which compiles without warnings.

// Needed to define the macros for data types in inttypes.h
#define __STDC_FORMAT_MACROS

// This part in header file (.h) re-used by this file as well as .c files compiled with C compiler
#ifdef __cplusplus
#include <cstdio>
#else
#include "stdio.h"
#endif

#include <cstdint>
#include <cinttypes>
#include <cstdio>

int main()
{
    int64_t i     = 0;
    printf("%" PRId64, i);
}

This looks like a good (the right?) solution for me.

jgreen81
  • 705
  • 1
  • 6
  • 14
  • 1
    Not really a good solution, because this code — as given — will not compile with a C compiler, and must be compiled with a C++ compiler. – Eljay Sep 16 '21 at 09:04
  • 1
    You will need to use `.h` for all includes in the C case (in the C case you will by the way find that `PRId64` is defined as `I64d`). Besides from that the solution seems fine. I will keep my answer since it still contains useful information. – nielsen Sep 16 '21 at 09:11
  • @Eljay My example is not so clear. Sorry for that. My intention was to show the contents of a header file re-used by both .c and .cpp files. I've updated the example above to make it a bit more clear. Perhaps I should have shown this as two separate snippets from the beginning but since all comments/answers depend on the way I wrote it, I haven't changed that. – jgreen81 Sep 16 '21 at 09:42