I've added this to my to-do list. Teensy's Print class really should give the same output as Arduino's.
But the Print class is doing exactly the same thing. It isn't an issue in the Print class.
The difference (issue) is happening above that in the actual sketch.
The code in the sketch is treating the char differently and so the call argument promotion of the "char" is handling
the sign bit differently.
The C standard allows the default behavior (sign-ness) for "char" to be chosen by the implementor,
I think that it is bit dumb, but hey thats what they decided.
It looks like AVR and ARM didn't pick the same default char behavior.
To me, the simple answer is if you want ARM basedd Teensy3 to have the same default char behavior as AVR,
then you have the ability to "make it so".
Use the -fsigned-char command-line option for Teensy3 compiles.
There are some other things that I consider "bugs" in the AVR with respect to "char" handling during argument call promotion.
There are certain loop conditions where the compiler will mis-optimize promotion when collapsing loops
and not properly clear the upper byte of the 16 bit int created during function call promotion.
The char behavior also changes if the char variable is declared as an automatic vs a static.
The AVR C guys claim the usage of the char in the example I provided was in an undefined area;
however, my read is that it was in an implementation dependent area.
I argued that undefined != implementation dependent are not the same and that the char promotion to called functions
should be handled the same regardless of surrounding code, declaration, or optimization used.
i.e. the implementation can pick how it wants to do it but then it must be consistent.
I lost the debate.
Keep in mind that this same behavior can affect the results you see in code like the original example code provided above.
The issue comes down to overflow/underflow/rollover and the behavior during those is undefined according to the standard.
The AVR C guys will say would you have preferred the the program crash when foo underflowed?
So just be careful that if you ever depend on overflow/underflow, it is not guaranteed to work
especially on AVR if you pass the variable as an argument to a function,
depending on your declaration and signess of the variable.
Anyway, as mentioned earlier, chars suck if used as 8 bit integers, since they are special and really aren't generic 8 bit values.
even if chars default to or if -fsigned-fsigned-char is effect,
"char" is not the same as a "signed char" - and this is required in the C standard.
The best thing is to NEVER use a char for anything but real chars.
Use uint8_t int8_t, ints etc... for your loops or even better consider using the c99 types
uint_fast8_t or int_fast8_t for types that do not have to be exactly 8 bits.
This allows the compiler to optimized as needed down to only 8 bits
if it helps optimize the code since depending on the processor the optimal bit size can be different.
BTW,
I sympathize with you on trying to convince Stallman of making/accepting changes to gcc.
I argued with him for quite some time back in the late 80's about relaxing structure member alignments.
(structure packing)
He would have nothing to do with it. I ended up having to create a custom version of the
m68k compiler to allow it. History has shown that he was on the wrong side of that one.
--- bill