SourceForge has been redesigned. Learn more.

Bug or not? Complement extends datatype

  • Andreas Schallenberg

    A small test app for 8051, SDCC v2.9.0:

    volatile unsigned char a = 0xf0;
    volatile unsigned char b = 0x0f;
    char main()
      if (a == ~b)
        return 0xaa;
      return 0xbb;

    Is compiled to:

    ;   D:\bug\main.c:6: if (a == ~b)
        mov r2,_b
        mov r3,#0x00
        mov a,r2
        cpl a
        mov r2,a
        mov a,r3
        cpl a
        mov r3,a
        mov r4,_a
        mov r5,#0x00
        mov a,r4
        cjne    a,ar2,00102$
        mov a,r5
        cjne    a,ar3,00102$
        C$main.c$8$2$2 ==.
    ;   D:\bug\main.c:8: return 0xaa;
        mov dpl,#0xAA
        C$main.c$10$1$1 ==.
    ;   D:\bug\main.c:10: return 0xbb;
        C$main.c$11$1$1 ==.
        XG$main$0$0 ==.
        mov dpl,#0xBB

    The comparison fails and 0xAA is returned, because
    both sides of the comparison are extended to 16 bits
    (int).  And 0x00f0 is obviously not equal to 0xfff0.

    I assume this is due to the complement operator.
    Is this correct behavior? I did not expect an implicit
    cast here.


  • Erik Petrich

    Erik Petrich - 2010-03-17

    Yes, this is correct. ISO/IEC 9899:1999 section "Unary arithmetic operators" paragraph 4 states: "The result of the ~ operator is the bitwise complement of its (promoted) operand (that is, each bit in the result is set if and only if the corresponding bit in the converted operand is not set). The integer promotions are performed on the operand, and the result has the promoted type. If the promoted type is an unsigned type, the expression ~E is equivalent to the maximum value representable in that type minus E." Parenthetical expressions are part of the original.

    Informally, the standard generally says that C operators promote integer types to at least an int before applying the operator, which in turn will cause the operator result to be at least an int. If you need the result to be a smaller type, you will need to add an explicit cast or assignment:

      if (a == (unsigned char)~b)


      b = ~b;
      if (a == b)

    (although, of course, this second example has the side effect of changing b)

  • Andreas Schallenberg

    Thank you for your quit response. I went for the explicit-cast solution. I wasn't aware that complement does lead to a type promotion, too. Now I'll be more careful.

  • Andreas Schallenberg

    That should read "quick response"… typo…


Log in to post a comment.