To be more precise, the compiler treats the constant as 16bit signed int or signed char. And because the constant is negative (sign bit is set). It is promoted to: 0b1111111111000000
If the constant was positive, then the original code would work as OP intuitively expected.. regardless of the promotion.
These are sneaky traps... if the constant was shifted to the right (arithmetic shift), it would be filled with ones from the left. i.e.: (0b11000000 >> 1) == 0b11100000
Edit: Now I am wondering what is the difference between automatic promotion and explicit casting.. I think that Int and short are both (at least) 16-bit signed integers here.. at least they should be. Otherwise the compiler is non-standard. Something strange is going on in this problem.. or I am just tired.
To be more precise, the compiler treats the constant as 16bit signed int or signed char. And because the constant is negative (sign bit is set). It is promoted to: 0b1111111111000000
If the constant was positive, then the original code would work as OP intuitively expected.. regardless of the promotion.
I wouldn't agree with that assesment. This compiler probably treats short as signed 8-bit, so the range of values is from -128 to 127. 0b11000000 is by default 16-bit and is interpreted as 192, which is outside of the range that can be represented by shorts. Therefore, no matter what value Position holds, it cannot be 192 and the comarison is always false.
The casting of 0b11000000 to short re-interprets it as -64, which is now in the range of shorts, and if Position is equal to -64 (0b11000000) the comparison is evaluated as true.
I wouldn't agree with that assesment. This compiler probably treats short as signed 8-bit, so the range of values is from -128 to 127. 0b11000000 is by default 16-bit and is interpreted as 192, which is outside of the range that can be represented by shorts. Therefore, no matter what value Position holds, it cannot be 192 and the comarison is always false.
The casting of 0b11000000 to short re-interprets it as -64, which is now in the range of shorts, and if Position is equal to -64 (0b11000000) the comparison is evaluated as true.
Ok.. so the problem is vice-versa to what I thought (well.. almost)? And only because the compiler is non-standard.. I would trash that compiler.
EDIT: Well, I was wrong in everything I said about how the constant 0b11000000 is treated.. I was (I am) tired. But, the confusion and problem here is probably the non-standard compiler behavior.
This is one of the reasons to use stdint.h for variables when using C in embedded software. The sizes of char , short , int , long and long long in C/C++ are dependent upon the implementation. "Integer promotions"/#define/constant can be a trapdoor with 8 bit controllers that tends to do the 'wrong' thing in this context.
#include <stdio.h>
#include <string.h>
main()
{
short Position = 1;
for(Position=1; Position != 0; Position++)
{
if(Position == 0b11000000) {
printf("%d",Position);
}
}
}
Also tested this with avr-gcc.. works fine:
C:
int main(void)
{
short Position;
for(Position=0; Position<255; Position++)
{
if(Position == 0b11000000) {
PORTB = 0xFF;
}
}
}
I have said it many times.. know your compiler.
Avr-gcc toolchain is the single reason I use AVR in my hobby projects and not PIC.
Arduino is great hardware, but the "sketch" is destroying programming skills..
Works fine in simulator (avr-gcc). I had breakpoints in both port-writes. Both breakpoints worked and variable Position had the correct value (192 and 0).
C:
int main(void)
{
signed short Position;
PORTB = 0x00;
for(Position=1; Position != 0; Position++)
{
if(Position == 0b11000000) {
PORTB = 0xFF;
}
}
if(PORTB == 0xFF)
{
PORTC=0xFF;
}
}
Not sure if my test was good enough.. I will test this at work tomorrow. Too lazy to get my development hardware up and running at home right now. I try to duplicate the OP situation.
In the absence of any suffix (U, u, L, l, LL, ll, ULL or ull ), a constant is assigned the “smallest” of the following types that can accommodate its value: short, unsigned short, int, unsigned int, long int, unsigned long int, long long or unsigned long long.
If you test the size of constant character sizeof('a'), it is 2 or 4 bytes regardless of the fact that "char" variable is always 8-bit (or smallest addressable unit.. practically always 8-bits).
Looks like "short" in the AVR compiler is 16-bit too. It's a huge mess in C that the lengths of the types (and even signed-ness) are not fixed by the standard. For compatibility, it's better to use int8_t surrogates, which are supposed to be the same for all compilers.