The compiler is configured to follow the -std=gnu++11 variant. Here are the flags: https://github.com/arduino/ArduinoCore-avr/blob/master/platf...
If you use other Arduino-compatible boards (e.g. ARM chips, ESP8266 or ESP32), they will use a different C++ compiler and different settings. See for example:
* SAMD uses 'arm-none-eabi-g++' (https://github.com/arduino/ArduinoCore-sam/blob/master/platf...)
* ESP8266 uses xtensa-lx106-elf-gcc (https://github.com/arduino/esp8266/blob/master/platform.txt)
* ESP32 uses xtensa-esp32-elf-gcc (https://github.com/espressif/arduino-esp32/blob/master/platf...)
So Arduino programming is "just" C++ with additional libraries and an IDE. Though I wrote "just" in quotes because they've done a lot of work to make things easier and approachable for beginners, so I don't want to diminish their work.
I think the answers I'm looking for are buried in those specifications. Gotta check them out, one of these days...
> So Arduino programming is "just" C++ with additional libraries and an IDE.
Considering that flag, I think it's something more (or less) than just plain C++...
It is an 8-bit chip, and that would take a number of cycles more, than to just leave them...?
And depending on the exact expression, it doesn't have to actually do anything differently - these integer conversions describe the expected result of the operation, not how it's performed in assembly. So when you write something like this:
char a, b, c;
...
a = b + c
the spec requires that b+c is treated as an int addition, but the resulting int is then assigned to a char variable, which basically truncates it. Furthermore, if b+c is larger than can fit in a char, then we have signed overflow (assuming that char is signed, which is usually the case), which is undefined behavior. Altogether, this means that the compiler can actually do an 8-bit addition here while remaining within the bounds of the spec.OTOH if the result is assigned to an int variable, then yeah, it'd have to promote them - but that would also be far less surprising to you than if it didn't, no?
Where this can potentially lead to more overhead than you'd expect is use of the temporary as input to another subexpresion. E.g. suppose we have this:
a = (b + c) / 2
Suppose b is 200 and c is 100. The spec requires that the result of this operation is 150, because b+c is performed on ints, and thus won't overflow. If it were an 8-bit addition of signed chars, assuming the typical wraparound behavior on overflow, you'd get 22.Indeed, though, on the Arduino platform, an int is usually 16 bit, but not because that's the chip's native archticture, but because that's the range required. Though I can't say for sure, I highly doubt (and now am actually almost completely certain in my doubts) that it would promote two chars to ints to perform operations on them, and last night also realized why, namely, there are counts for the number of cycles required to do operations on various data types [0].
If what you say about integer promotion is true, there would be no difference in clock cycles between an int and a byte, but there is.
So in essence, no, the Arduino is definitely somehow deviating from spec when it comes to promotion.
[0]: https://forum.arduino.cc/index.php?topic=92684.msg696420#msg...
EDIT: I just realized, I think I need to actually look into the (Atmel's) AVR specs, as the Arduino IDE is basically just a wrapper for that.
But, again, this would only manifest in expressions where you mix operators, or try to assign the result to a variable of a broader type. So (a+b+c) could still be evaluated entirely in 8 bits without becoming non-conforming, if target is a char, and ditto for (a-b-c) etc. So long as you know that only the last 8 bits of the result is all that matters, the promotion can be disregarded. It's only when you apply some other operator - multiplication, division, bit shift, or comparison - to the intermediate result that you can observe the increased width. But that doesn't actually happen all that often.
(Conversely, it might also mean that it is not conforming, but there are relatively few practical cases where it actually manifests.)
I am not exactly certain, but what I think happens is that when you define your charType variable that the upper bytes in the word are still the same random data, so when you multiply without casting, it is treating the char as an int and multiplying the whole 4 bytes. When you cast, it probably just multiplies the lowest byte and carries if necessary. I am also not certain if the compiler would optimize to using a shift operation if one operand is a multiple of 2.
Again, not exactly certain if this is the case, but it's similar to what I've noticed.
char foo;
may be signed or unsigned depending on the architecture and compiler, which may lead to surprising results.
Does anyone know for sure whether or not the Arduino compiler deviates from this standard, or ever had, in previous versions?
Does multiplication qualify as a binary operator?
IIRC, I think I was compound multiplying the product of an int and a char into a long (see below), and I had to explicitly cast the char as int to get the right results, much to my surprise, as I had expected the char to get promoted to an int. But I could also have made some mistakes, it's been awhile...
EDIT: Found my old code snippet, and it kinda invalidates my original question, what I was actually doing was which leads the right side to evaluate first without promotion, thus modulating the end result by 256, which was not intended. I then cast all of them as long, but probably (certainly!...?) only one would've been enough.EDIT2: Or at least, two of them have to be casted, else it might evaluate two chars first, modulating the result, before actually promoting to long to multiply with another long. (Or not, because it promotes to the most significant data type on the right side? Ugh... this is why I prefer to be extra verbose.)