C is a strongly typed language. Implicit casting, particularly between signed and unsigned values, can cause all kinds of hard-to-debug problems in programs. Yet the Arduino documentation never shows return types.
Just as an example, SoftwareSerial::available() says:
Returns
The number of bytes available to read.
Great. So is this a signed value or an unsigned value? Is it a byte, 16 bits, 32 bits? Because the documentation is silent. These things matter.
It's so pervasive in the documentation I have to conclude it was a conscious choice. But why?
That just doesn't make sense. How does a beginner benefit from having that hidden from him?
Strong typing is a really, really important concept in C. Imagine a beginner assuming that available() returns an unsigned value -- the documentation doesn't mention that it could return -1, after all. So they put it the return value into an unsigned variable. Then they check for it being greater than zero. When the return value is -1 their program is going to blow up.
When it comes to C, it is not strongly typed. While it does have a static type system, it allows many implicit conversions between types, permits casting between incompatible types (including between pointers and integers), and offers mechanisms like unions and void* that bypass type safety. These features make it weakly typed compared to languages with stricter type enforcement.
So not really in C. C++ (which we use) is indeed more stringent but still pretty permissive.
For exemple Swift enforces strict type matching in arithmetic, so mixing types like Int and Float requires explicit conversion. It rejects implicit numeric promotions that C++ allows freely, where an int can automatically become a float or vice versa.
This strictness in Swift prevents unintended loss of precision, rounding errors, or logic bugs that can arise in C++ when implicit conversions silently change how values are interpreted or calculated.
FWIW, various code assistance features in the IDE show the signatures, based on the source. More reliable than documentation
For the ESP32 HTTPClient, a request stream can be merely temporarily empty; only when less-than-nothing is available (or the total-to-write len, if any, is satisfied) is it done
// read all data from stream and send it to server
while (connected() && (stream->available() > -1) && (len > 0 || len == -1)) {
// get available data size
int sizeAvailable = stream->available();
if (sizeAvailable) {
so weird stuff in the code... ( When a uint32_t value is implicitly converted to a 32-bit signed int , the bit pattern remains the same but the value is interpreted as signed. If the uint32_t value is greater than INT_MAX (2,147,483,647), the resulting int will be negative due to overflow in two's complement representation. This never happens due to the size of our buffers, but it's not great IMHO).
Not all (char...) have a signdness and none has a strict byte count. That sloppyness lead to many weak standard functions with mixed up types (int instead of char...). And that weak typing had to be propagated into any new C version. Stronger types only have been introduced in header files which can be changed in any new version.
Can somebody explain what is so strong in C types?
Nothing is perfect and I can say as a beginner these things were never an issue ( everything was 8 bits , so bytes were obvious )
Stuff has expanded rapidly since those times and we now have 16 and 32 bit processors , dual cores etc and maybe documentation has been left behind is some places.
In practice it’s not been an issue for me - if I’m not sure what a function returns , i try it and then I know , and different processors may respond differently and some functions designed at while back , not work at all .
It’s a rare issue anyway and you soon pick up any perceived “ vagueness “- but next week it may change !!
The thing is that when it’s not in the documentation then it can change as you say and if you took it for granted that things would be a certain way, then you might be in for a sometimes costly surprise…
I don't think so. The reason is the Arduino Language Reference system was recently reworked and that repository is no longer the source from which the content is generated. I'm not sure whether the documentation team monitors the previous repository so raising an issue may be fruitless.
The new repository where the source is hosted and developed is private, so there is no longer a public issue tracker where the community can check to see whether a given issue has already been reported.
Unfortunately it is no longer possible for the community to participate in the development of the Arduino Language Reference.
It's not like "knowing" that Serial.available() returns an "int" actually lets you know whether it's 16 or 32 bits, or ever returns a negative number... For a "typed" language, "int" is ... very vague.
True, there are better types like size_t or uint16_t or int_fast8_t in modern specs, but then you're starting to require a more "advanced" understanding of ... things. (*int_fast*_t types seem woefully underused, when considered objectively. Probably because it's "too much typing."
That doesn't mean that the documentation shouldn't say "returns an int"
The exact byte count should be left to the machine library. That's the original idea behind those vague types.
At these days even the size of a byte could be anything between 5 to 12 bits, that's why "char" was the replacement type for a byte, and a 8-bit "byte" now is named "octet" in French language.
I really admire the Delphi "subrange" type, which gives the exact range of allowed values. The compiler allocates enough bytes for such a type and (optionally) checks for out-of-bounds errors in assignments. One obvious use is the index range of an array.
If Arduino wanted to position itself as a simplified subset of C++ -- which it seems to be trying to do -- one logical thing would be to enforce that the libraries, at least in their public interfaces, use a simplified and greatly reduced set of types. I'd rather conceal from the programmer what the size of an int is than what functions return.