This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

BUG with bits in integer variable

There is a BUG in the compilation of a bit definition:

unsigned int bdata my_int;
sbit bit15 = my_int ^ 15;
sbit bit7 = my_int ^ 7;

void main()
{
  my_int = 0x8000;

  if(bit15)
  {
    // Here we shall not appear,as compiller
    // will be erroneous to check 7-bit of
    // a variable my_int instead of 15-bit
    // (as this variable place in memory in
    // little endian order)
    // ...
  }

  if(bit7)
  {
    // oops! we here!
    // ...
  }
}
This is a BUG! Please correct. Thanx.

Parents
  • hi,

    unsigned int bdata my_int;
    sbit bit15 = my_int ^ 15;
    sbit bit7 = my_int ^ 7;
    

    So what it does:

    - first line allocates two bytes of memory inside bit-addressable memory space to place integer number there and names variable as my_int;
    - second and third lines declare two variables: bit7 and bit15. These variables are defined as 7th and 15th bits of bit-addressable memory space related from address where variable my_int has been placed. Important note: lines like
    bitX = variable ^ X;
    HAVE NOTHING with the variable; they are related to the address where the variable is placed at. Due Keil uses big-endian storing format so it holds MSB of integer firstly then LSB.

    Bits in data of any width are always 0 - LSB, etc. up to MSB.

    The native C does not support bit variables at all. ANSI C supports bit-fields only. Such questions as bit-field placement, bits' order and how many bytes are utilized per bitfield - are not defined by ANSI C. It says: "compiler-dependence, read its manual".

    Now come back to your code. For me it is clean and should be translated to:
    void main()
    {
      my_int = 0x8000;
    
      if((my_int & 0x8000) != 0)  // check for bit 15
      {
      }
      if((my_int & 0x0080) != 0) // check bit 7
      {
      }
    }
    
    Regards,
    Oleg
    

Reply
  • hi,

    unsigned int bdata my_int;
    sbit bit15 = my_int ^ 15;
    sbit bit7 = my_int ^ 7;
    

    So what it does:

    - first line allocates two bytes of memory inside bit-addressable memory space to place integer number there and names variable as my_int;
    - second and third lines declare two variables: bit7 and bit15. These variables are defined as 7th and 15th bits of bit-addressable memory space related from address where variable my_int has been placed. Important note: lines like
    bitX = variable ^ X;
    HAVE NOTHING with the variable; they are related to the address where the variable is placed at. Due Keil uses big-endian storing format so it holds MSB of integer firstly then LSB.

    Bits in data of any width are always 0 - LSB, etc. up to MSB.

    The native C does not support bit variables at all. ANSI C supports bit-fields only. Such questions as bit-field placement, bits' order and how many bytes are utilized per bitfield - are not defined by ANSI C. It says: "compiler-dependence, read its manual".

    Now come back to your code. For me it is clean and should be translated to:
    void main()
    {
      my_int = 0x8000;
    
      if((my_int & 0x8000) != 0)  // check for bit 15
      {
      }
      if((my_int & 0x0080) != 0) // check bit 7
      {
      }
    }
    
    Regards,
    Oleg
    

Children
  • Hi.

    Keil realy transletes my code to this:

    unsigned int bdata my_int;
    sbit bit15 = my_int ^ 15;
    sbit bit7 = my_int ^ 7;
    
    void main()
    {
      my_int = 0x8000;
    
      if((my_int & 0x0080) != 0)  // <- if(bit15)
      {
      }
      if((my_int & 0x8000) != 0)  // <- if(bit7)
      {
      }
    }
    
    But the code will be translate correctly if I at once shall write so (without "sbit x=y^n"):
    void main()
    {
      my_int = 0x8000;
    
      if((my_int & 0x8000) != 0)  // check bit 15
      {
      }
      if((my_int & 0x0080) != 0)  // check bit 7
      {
      }
    }
    

  • sbit bit15 = my_int ^ 15;

    you can only use sbit for bit addressable bytes

    Erik

  • Do you read Cx51 User's Guide? Probably, no. Here a part from it:
    --------------------------------------------
    Bit-Addressable Objects

    Bit-addressable objects are objects that may be addressed as words or as bits. Only data objects that occupy the bit-addressable area of the 8051 internal memory fall into this category.

    The Cx51 Compiler places variables declared with the bdata memory type into the bit-addressable area. Furthermore, variables declared with the bdata memory type must be global (declared outside the scope of a function). You may declare these variables as shown below:

    int bdata ibase;        /* Bit-addressable int */
    
    char bdata bary [4];    /* Bit-addressable array */
    
    The variables ibase and bary are bit-addressable. Therefore, the individual bits of these variables may be directly accessed and modified. Use the sbit keyword to declare new variables that access the bits of bdata variables. For example:
    sbit mybit0 = ibase ^ 0;      /* bit 0 of ibase */
    sbit mybit15 = ibase ^ 15;    /* bit 15 of ibase */
    
    sbit Ary07 = bary[0] ^ 7;     /* bit 7 of bary[0] */
    sbit Ary37 = bary[3] ^ 7;     /* bit 7 of bary[3] */
    
    The above example represents declarations, not assignments to the bits of the ibase and bary bdata variables. The expression following the carat symbol ('^') in the example specifies the position of the bit to access with this declaration. This expression must be a constant value. The range depends on the type of the base variable included in the declaration. The range is 0-7 for char and unsigned char, 0-15 for int, unsigned int, short, and unsigned short, and 0-31 for long and unsigned long.

  • Isn't it interesting that when the software does not behave in the way someone want it to do (forget what the manual says) it is always a BUG. Never a "problem" "possible misunderstanding" no absolutely a BUG!

    Erik