C Code Help - Type Cast

Status
Not open for further replies.

Suraj143

Active Member
I use mikroC.

The following code does not work.

short Position;
int Error = 0;

Code:
if (Position == 0b11000000) Error =  -6 ;

But this code works.

int Position;
int Error = 0;

Code:
if (Position == 0b11000000) Error =  -6 ;

When the Position register is "int" type the code works.Can somebody explain me this.
 
The "0b11000000" is a constant... The compiler treats constants in different ways.... In this case its an int..

C:
short Position;
int error = 0;

if(Position == (short)0b11000000) error = 1;
 
Very nice.you are correct.When I type cast the constant as in your example the code worked.

Thank you very much.
 
The "0b11000000" is a constant... The compiler treats constants in different ways.... In this case its an int..

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.
 
Last edited:

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.
 
Last edited:
I ran this code in here: http://www.compileonline.com/compile_c_online.php
works fine. (prints: "192")
C:
#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..
 
Last edited:
The online one is running on Linux, so short is 16-bit. You would need 0b1100000000000000 (or 0xc000) to get the same effect.

I don't know about AVR, but I guess short is unsigned by default. Try it with "signed short".
 
If "short" is unsigned by default in avr-gcc, I will throw my computer out the window. Testing...
 
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.
 
This does not work (does not print "192") in http://www.compileonline.com/compile_c_online.php:

C:
main()
{
   short Position = 1;
   int Error = 0;

   for(Position=1; Position < 255; Position++)
   {
       if(Position == (signed char)0b11000000) {
           printf("%d",Position);
       }
   }
}
casting the binary constant to (unsigned char) works.

This does not work either (same online compiler). Prints nothing.
C:
main()
{
   signed char Position = 1;
   int Error = 0;
 
   for(Position=1; Position < 255; Position++)
   {
       if(Position == 0b11000000) {
           printf("%d",Position);
       }
   }
}

So, my conclusion is that MicroC uses non-standard "short" -variable.
 
.. deleted this test.. something went wrong. Sorry if I'm flooding.
 
Last edited:

So the cast to short was a load of bull.... According to them a un-suffixed constant should be a short anyway...
 
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.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…