__cplusplus defined for C99 without a framework

Here is my platformio.ini:

  • I use Standard peripheral library with bluepill.
  • I don’t use any framework .
  • I use -std=c99 build flag

I was wondering why __cplusplus is defined in system headers - for example in .platformio\packages\toolchain-gccarmnoneeabi\arm-none-eabi\include\assert.h - Intellisense shows __cplusplus 201402L.

But not in the main.c (greyed out):

I was able to circumvent this behaviour with build_unflags = __cplusplus, but still am wondering why it is inconsistent and where those flags are defined.

This unfortunately doesn’t fix the problem that I am getting single letter per line when printing asserts, but I guess that’s a different issue:…

That’s a phantom. During compilation, __cplusplus will be automatically defined by the compiler (to the given -std=c++/gnu++YY version or the standard fallback version) when a .cpp file is compiled and in all subsequent headers it includes. Meaning, if you have a main.c and it #include <assert.h>, then __cplusplus would not be defined in that compiled run, but a main.cpp doing the same would include the header with __cplusplus defined.

What VSCode shows you (and this can be different from what’s happening during compilation) is dependent on whether you let it interpret the header as “included from a C file” or “included from a C++” file. As documtend here, that is depending on the “file association setting” (and not e.g. the “C/C++” button in the VSCode taskbar).

And hence, it becomes clear that when looking at assert.h with the default .h.cpp association, it looks like

and when I go into the .vscode/settings.json and add the appropriate “interprete every header file in C mode” setting

then it immediately looks like

and now __cplusplus is not defined, but __STDC_VERSION is. As expected, to January 1999.


Again, this had 0 effect on the actual compilation, it’s just a visual thing with the VSCode intellisense.

It also follows that you do not want to manually define or undefine the __cplusplus macro. You only control that

  1. it is activated in a compilation unit at all if its a .cpp file or a header included from such a file
  2. you control the value of it by controlling the value of -std=c++/gnu++<version> setting, e.g., via advanced scripting (env["CXXFLAGS"], env["CFLAGS"] for C++ and C respectively) if it needs changing from the default.
1 Like

My guess on that is that the computer is too fast / the microcontroller to slow, and when with --specs=rdimon it prints a character, OpenOCD immediately pushes it to GDB (with the “to be output text” packet containing only one char) which outputs it to its stdout (not sure if with or without line ending) and then also in VSCode. That happens for every char then. The interpretation might be different if you started OpenOCD and GDB on a commandline alone and connected them to each other, the line endings may be correct then.

I.e., in one terminal

cd C:\Users\<user>\.platformio\packages\tool-openocd
bin\openocd.exe -d2 -s scripts -f interface/stlink.cfg -c "transport select hla_swd" -f target/stm32f1x.cfg

and in another one

cd C:\Users\<user>\.platformio\packages\toolchain-gccarmnoneeabi\bin
arm-none-eabi-gdb -ex "target extended-remote :3333" -ex "monitor reset run"

Thank you for these answers.
This gave me insights into what is going on many levels.

As for the assert,

OpenOCD printed assert horizontally:

assertion "0" failed: file "src\APP\main.c", line 247, function: main
semihosting: application exception 0x20004fb0
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x0800845e msp: 0x20004fb0, semihosting

, however, unlike usual printf(), it was printed out like a smooth animation. I.e. unbuffered - character by character.

Looking into newlib-nano, I can see the printing is done to stderr. If I redefine the __assert_func and use ‘stdout’ instead the line is buffered, and debug console prints it all at once.

(void) printf("\nAssertion \"%s\" failed: file \"%s\", line %d%s%s\n",
		failedexpr, file, line,
		func ? ", function: " : "", func ? func : "");

I prefer to redefine __assert_func anyway, since I’d rather stop on breakpoint (__asm__("BKPT");), than hardfault with newlib’s abort().


You might be able to leave the __assert_func alone and give the stderr a buffer, similiar for how this disabled the buffer, with setvbuf().

1 Like

I tried and it worked.

#ifdef DEBUG
volatile char stderrBuff[100]; //used by assert
int main (void)
	#ifdef DEBUG
	if(setvbuf(stderr, stderrBuff, _IOLBF, sizeof(stderrBuff))){

~But I am still going to redefine it __assert_func because having __asm__("BKPT") instead of abort() makes debugging a better experience in practice.~

void __assert_func(const char *file, int line, const char *func, const char *failedexpr) {
	(void) printf("\nAssertion \"%s\" failed: file \"%s\", line %d%s%s\n",
		failedexpr, file, line,
		func ? ", function: " : "", func ? func : "");
   __ASM("bkpt 3");

Edit: redefined function needs to be non-return type, per the non-return attribute in assert.h. If it returns, the behavior is undefined and in my case it was making a parent function not returning immediately. So that’s defets the purpose and separate debug_assert() should be defined or simply __ASM(“bkpt 3”); used.