Diferencia entre scanf () y strtol () / strtod () en los números de análisis

Nota: Revisé completamente la pregunta para reflejar de manera más apropiada para qué estoy estableciendo la recompensa. Por favor, disculpe cualquier inconsistencia con las respuestas ya dadas que esto podría haber creado. No quería crear una nueva pregunta, ya que las respuestas anteriores a esta podrían ser útiles.

Estoy trabajando en la implementación de una biblioteca estándar de C, y estoy confundido acerca de una esquina específica del estándar.

El estándar define los formatos de número aceptados por elscanf familia de funciones (% d,% i,% u,% o,% x) en términos de las definiciones parastrtol, strtoulystrtod.

La norma también dice quefscanf() solo devolverá un máximo de un carácter en el flujo de entrada y, por lo tanto, algunas secuencias aceptadas porstrtol, strtoul ystrtod son inaceptables parafscanf (ISO / IEC 9899: 1999, nota de pie de página 251).

Intenté encontrar algunos valores que exhibieran tales diferencias. Resulta que el prefijo hexadecimal "0x", seguido de un carácter que no es un dígito hexadecimal, es uno de esos casos en que las dos familias de funciones difieren.

Curiosamente, se hizo evidente que no hay dos bibliotecas de C disponibles que estén de acuerdo con la salida. (Consulte el programa de prueba y la salida de ejemplo al final de esta pregunta).

Lo que me gustaría escuchar es¿Qué se consideraría un comportamiento conforme a la norma en el análisis "0xz"?. Lo ideal es citar las partes relevantes de la norma para hacer el punto.

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

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", &u, &count );
    printf( "fscanf:  Returned %d, result %2d, consumed %d\n", rc, u, count );
    rewind( fh );

    /* strtoul base 16 */
    u = strtoul( culprit, &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", &i, &count );
    printf( "fscanf:  Returned %d, result %2d, consumed %d\n", rc, i, count );
    rewind( fh );

    /* strtol base 0 */
    i = strtol( culprit, &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
*/

Respuestas a la pregunta(7)

Su respuesta a la pregunta