title: Difference between scanf() and strtol() / strtod() in parsing numbers
body: <p><strong>Note:</strong> I completely reworked the question to more properly reflect what I am setting the bounty for. Please excuse any inconsistencies with already-given answers this might have created. I did not want to create a new question, as previous answers to this one might be helpful.</p>
  
  <hr>
  
  <p>I am working on implementing a C standard library, and am confused about one specific corner of the standard.</p>
  
  <p>The standard defines the number formats accepted by the <code>scanf</code> function family (%d, %i, %u, %o, %x) in terms of the definitions for <code>strtol</code>, <code>strtoul</code>, and <code>strtod</code>.</p>
  
  <p>The standard also says that <code>fscanf()</code> will only put back a maximum of one character into the input stream, and that therefore some sequences accepted by <code>strtol</code>, <code>strtoul</code> and <code>strtod</code> are unacceptable to <code>fscanf</code> (ISO/IEC 9899:1999, footnote 251).</p>
  
  <p>I tried to find some values that would exhibit such differences. It turns out that the hexadecimal prefix "0x", followed by a character that is not a hexadecimal digit, is one such case where the two function families differ.</p>
  
  <p>Funny enough, it became apparent that no two available C libraries seem to agree on the output. (See test program and example output at the end of this question.)</p>
  
  <p>What I would like to hear is <strong>what would be considered standard-compliant behaviour in parsing "0xz"?</strong>. Ideally citing the relevant parts from the standard to make the point.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;assert.h&gt;
  
  int main()
  {
      int i, count, rc;
      unsigned u;
      char * endptr = NULL;
      char culprit[] = "0xz";
  
      /* File I/O to assert fscanf == sscanf */
      FILE * fh = fopen( "testfile", "w+" );
      fprintf( fh, "%s", culprit );
      rewind( fh );
  
      /* fscanf base 16 */
      u = -1; count = -1;
      rc = fscanf( fh, "%x%n", &amp;u, &amp;count );
      printf( "fscanf:  Returned %d, result %2d, consumed %d\n", rc, u, count );
      rewind( fh );
  
      /* strtoul base 16 */
      u = strtoul( culprit, &amp;endptr, 16 );
      printf( "strtoul:             result %2d, consumed %d\n", u, endptr - culprit );
  
      puts( "" );
  
      /* fscanf base 0 */
      i = -1; count = -1;
      rc = fscanf( fh, "%i%n", &amp;i, &amp;count );
      printf( "fscanf:  Returned %d, result %2d, consumed %d\n", rc, i, count );
      rewind( fh );
  
      /* strtol base 0 */
      i = strtol( culprit, &amp;endptr, 0 );
      printf( "strtoul:             result %2d, consumed %d\n", i, endptr - culprit );
  
      fclose( fh );
      return 0;
  }
  
  /* newlib 1.14
  
  fscanf:  Returned 1, result  0, consumed 1
  strtoul:             result  0, consumed 0
  
  fscanf:  Returned 1, result  0, consumed 1
  strtoul:             result  0, consumed 0
  */
  
  /* glibc-2.8
  
  fscanf:  Returned 1, result  0, consumed 2
  strtoul:             result  0, consumed 1
  
  fscanf:  Returned 1, result  0, consumed 2
  strtoul:             result  0, consumed 1
  */
  
  /* Microsoft MSVC
  
  fscanf:  Returned 0, result -1, consumed -1
  strtoul:             result  0, consumed 0
  
  fscanf:  Returned 0, result  0, consumed -1
  strtoul:             result  0, consumed 0
  */
  
  /* IBM AIX
  
  fscanf:  Returned 0, result -1, consumed -1
  strtoul:             result  0, consumed 1
  
  fscanf:  Returned 0, result  0, consumed -1
  strtoul:             result  0, consumed 1
  */
  </code></pre>