JB Enterprises

JB Enterprises - Johan Bezem

Interim Management & Consulting

JB Enterprises - Blog


Why 32768 isn’t always the same as 0x8000

Contrary to intuition, the C constants "32768" and "0x8000" have an identical representation (0x8000), but possibly different types in C. If you consider a processor with a 16-bit int type, and a 32-bit long type, 32768 is considered long, whereas 0x8000 (and the octal variant 0100000) is considered unsigned int.

If you feel the need, check the C standard at http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf, page 55 at the bottom, and the table at page 56 (or look at Harbison & Steele, 5th edition, and look at section 2.7.1 page 24ff).

Normally, there is no problem when using such values, since the representations are identical.
However, consider this small example:

  #define C_DECIMAL     32768
  #define C_HEXADECIMAL 0x8000
  
  void main(int argc, char *argv[])
  {
    volatile long long_dec = ((long)~C_DECIMAL);
    volatile long long_hex = ((long)~C_HEXADECIMAL);
    
    return;
  }
  

When C_DECIMAL is considered long, the negation will invert 32 bits, resulting in a representation 0xFFFF7FFF with type long; the cast is superfluous.
When C_HEXADECIMAL is considered unsigned int, the negation will invert 16 bits, resulting in a representation 0x7FFF with type unsigned int; the cast will then zero-extend to a long value of 0x00007FFF.

Checking with a 16-bit integer compiler (CW7.1 ColdFire using "-intsize 2"):

  0x00000000                    _main:
  ;                             main:
  0x00000000  0x4E560000               link     a6,#0
  0x00000004  0x518F                   subq.l   #8,a7
  0x00000006  0x223CFFFF7FFF           move.l   #-32769,d1
  0x0000000C  0x2D41FFF8               move.l   d1,-8(a6)
  0x00000010  0x223C00007FFF           move.l   #32767,d1
  0x00000016  0x2D41FFFC               move.l   d1,-4(a6)
  0x0000001A  0x4E5E                   unlk     a6
  0x0000001C  0x4E75                   rts
  

For those of you who do not know how to read assembler code I have made the differing values italic. So the compiler confirms the difference in behavior, and this is not a compiler error.

Lucky you if you have Lint to warn you. (Yes, I know, other tools will too, if you let them...)

Happy coding!

March 5th, 2009

Valid XHTML 1.0 Strict Valid CSS www.bezem.de: © 1999 – 2024 by Johan Bezem, all rights reserved.
This page was last updated on Tuesday, 2017-07-25 17:31.