if (Serial) and while(!Serial), under the hood

Hi. This question is more for my education on C++ in an Arduino context, (and this might take a little explaining before I actually ask the question). I wanted to understand the behaviour of the if(Serial){}; or while (!Serial){}; tests for serial connection.

I’ve read https://www.arduino.cc/en/Serial/IfSerial And looked through the C++ libraries where Serial_ is defined, and Serial is instantiated. (Mostly CDC.cpp and USBAPI.h, but there are others USBDesc.h, USBCore.h). But I want to understand it better, at a language level.

My understanding of C++ is that when testing the name of a variable you are basically testing whether it is a null pointer or not. As testing of a null pointer returns false. (Such as testing a pointer to a location on the heap, to make sure there was enough memory to allocate the variable). But in the examples shown in the Arduino doco Serial has already been instantiated, and even called, most of he time. The while(!Serial) test is often employed after calling the Serial.begin(); method, which means the object must already exist, and not be a null pointer, otherwise the calling of the method would fail. But the while(!Serial) is called anyway.

This confuses me, and I’m thinking there’s some behaviour in C++ that I must have missed. I read that the Serial operation was asynchronous, but we’ve still already used a method (begin) on the object, so it’s instantiated. Does it become un-instantiate somehow, then reinstantiated once the connection takes place? Or does Serial become dereferenced somehow if a connection can’t be made? Or is it really just superfluous?

The only other thing I can think of is that there’s an overloaded operator being employed in this test, but I can’t see that in the CDC.cpp, or the USBAPI.h files anywhere.

i only see examples of (Serial.available()) tested as a condition. Serial.available() return the number of bytes in the Serial buffer.

ADEPoch: The only other thing I can think of is that there's an overloaded operator being employed in this test [...]

In the HardwareSerial class (in HardwareSerial.h), there is this declaration:

operator bool() { return true; }

This allows the "Serial" object (defined by the "extern HardwareSerial Serial;" declaration) to be used as if it were a boolean value. It would appear that calling this before the object is instantiated will return false ... once created, the overloaded operator returns true.

This returns 0 then 1:

int value = Serial;
void setup()
{
  Serial.begin(115200);
  delay(5000);
  Serial.println(value);
  Serial.println(Serial);
}

ADEPoch: The only other thing I can think of is that there's an overloaded operator being employed in this test, but I can't see that in the CDC.cpp, or the USBAPI.h files anywhere.

https://github.com/arduino/ArduinoCore-avr/blob/6ba4fd363f8dcd704b73d6b4dd897fce6e7bfa72/cores/arduino/USBAPI.h#L108

https://github.com/arduino/ArduinoCore-avr/blob/b7c607663fecc232e598f2c0acf419ceb0b7078c/cores/arduino/HardwareSerial.h#L135

https://github.com/arduino/ArduinoCore-avr/blob/b7c607663fecc232e598f2c0acf419ceb0b7078c/cores/arduino/CDC.cpp#L245-L258

This confuses me, and I'm thinking there's some behaviour in C++ that I must have missed.

You are experiencing The magic of the bool operator in C++ here on core AVR (always true) or here for example on en ESP8266

Edit: too slow looking for those URL, previous answers corrct

So THAT'S how this works! I was wondering too... More interesting is the USBSerial version of this, with it's non-trivial implementation: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/CDC.cpp#L245