title: What is the purpose of the h and hh modifiers for printf?
body: <p>Aside from <code>%hn</code> and <code>%hhn</code> (where the <code>h</code> or <code>hh</code> specifies the size of the <em>pointed-to</em> object), what is the point of the <code>h</code> and <code>hh</code> modifiers for <code>printf</code> format specifiers?</p>
  
  <p>Due to default promotions which are required by the standard to be applied for variadic functions, it is impossible to pass arguments of type <code>char</code> or <code>short</code> (or any signed/unsigned variants thereof) to <code>printf</code>.</p>
  
  <p>According to 7.19.6.1(7), the <code>h</code> modifier:</p>
  
  <blockquote>
    <p>Speciﬁes that a following d, i, o, u, x, or X conversion speciﬁer applies to a
    short int or unsigned short int argument (the argument will
    have been promoted according to the integer promotions, but its value shall
    be converted to short int or unsigned short int before printing);
    or that a following n conversion speciﬁer applies to a pointer to a short
    int argument.</p>
  </blockquote>
  
  <p>If the argument was actually of type <code>short</code> or <code>unsigned short</code>, then promotion to <code>int</code> followed by a conversion back to <code>short</code> or <code>unsigned short</code> will yield the same <em>value</em> as promotion to <code>int</code> without any conversion back. Thus, for arguments of type <code>short</code> or <code>unsigned short</code>, <code>%d</code>, <code>%u</code>, etc. should give identical results to <code>%hd</code>, <code>%hu</code>, etc. (and likewise for <code>char</code> types and <code>hh</code>).</p>
  
  <p>As far as I can tell, the only situation where the <code>h</code> or <code>hh</code> modifier could possibly be useful is when the argument passed it an <code>int</code> outside the range of <code>short</code> or <code>unsigned short</code>, e.g.</p>
  
  <pre><code>printf("%hu", 0x10000);
  </code></pre>
  
  <p>but my understanding is that passing the wrong type like this results in undefined behavior anyway, so that you could not expect it to print 0.</p>
  
  <p>One real world case I've seen is code like this:</p>
  
  <pre><code>char c = 0xf0;
  printf("%hhx", c);
  </code></pre>
  
  <p>where the author expects it to print <code>f0</code> despite the implementation having a plain <code>char</code> type that's signed (in which case, <code>printf("%x", c)</code> would print <code>fffffff0</code> or similar). But is this expectation warranted?</p>
  
  <p>(Note: What's going on is that the original type was <code>char</code>, which gets promoted to <code>int</code> and converted back to <code>unsigned char</code> instead of <code>char</code>, thus changing the value that gets printed. But does the standard specify this behavior, or is it an implementation detail that broken software might be relying on?)</p>