title: %ld format conversion for portability
body: <p>I have a code base which is intended to compile without warnings and run without any glitches on multiple architectures, all x86:  MSDOS, Windows 32 console mode, Windows 32 GUI mode, Linux 32, and Linux 64.</p>
  
  <p>Before adding support of Linux 64, this was easy.  Almost all data were declared as either <code>int</code> or from the typedefs for BYTE, WORD, and DWORD:</p>
  
  <pre><code>typedef unsigned char   BYTE;
  typedef unsigned short  WORD;
  typedef unsigned long   DWORD;
  </code></pre>
  
  <p>Upon adding 64-bit gcc support, DWORD needed a little tweaking to remain as a 32 bit value since it represented stored data:</p>
  
  <pre><code>// to compile DWORDs as 32 bits on 64-bit machines:
  #if __x86_64__
   typedef unsigned int    DWORD;
  #else
   typedef unsigned long   DWORD;
  #endif
  </code></pre>
  
  <p>And this worked nicely on all environments:</p>
  
  <pre><code>DWORD   data;
  printf ("%lu", data);
  </code></pre>
  
  <p>However, <code>gcc -Wall</code> now complains about format conversions:</p>
  
  <pre><code>warning: format ‘%ld’ expects argument of type ‘long int’, but argument
           1 has type ‘DWORD {aka unsigned int}’ [-Wformat]
  </code></pre>
  
  <p>Due to the extensive formatting this code does&mdash;thousands of lines of output formatting&mdash;I'd rather not retrofit a type specific formatter.  A similar question was <a href="https://stackoverflow.com/a/2524675/198536">answered by using the <code>z</code> modifier</a>:</p>
  
  <pre><code>printf ("%zu", data);
  </code></pre>
  
  <p>But that makes Turbo C on MSDOS and Win32 console do something odd:  It shows the conversion specification <code>%zu</code> as output instead of converting anything.</p>
  
  <p>Is there a cleaner way to handle the variability of the type in a way that goes with the grain of printf and the fundamental data types?</p>