¿Por qué scanf(“%hhu”, char*) sobrescribe otras variables cuando son locales?

3 minutos de lectura

¿Por que scanfhhu char sobrescribe otras variables cuando son locales
daniel castro

El título lo dice todo. Estoy usando GCC 4.7.1 (incluido con CodeBlocks) y enfrenté un problema extraño. Considera esto:

int main() {
    unsigned char a = 0, b = 0, c = 0;
    scanf("%hhu", &a);
    printf("a = %hhu, b = %hhu, c = %hhu\n", a, b, c);
    scanf("%hhu", &b);
    printf("a = %hhu, b = %hhu, c = %hhu\n", a, b, c);
    scanf("%hhu", &c);
    printf("a = %hhu, b = %hhu, c = %hhu\n", a, b, c);
    return 0;
}

Para las entradas 1, 2 y 3, esta salida

a = 1, b = 0, c = 0
a = 0, b = 2, c = 0
a = 0, b = 0, c = 3

Sin embargo, si declaro a, b y c como variables globales, funciona como se esperaba. ¿Por qué sucede esto?

Gracias de antemano

Otros detalles:

Estoy ejecutando Windows 8 de 64 bits. También probé con -std=c99 y el problema persiste.

Más investigación

Probando este código

void printArray(unsigned char *a, int n) {
    while(n--)
        printf("%hhu ", *(a++));
    printf("\n");
}

int main() {
    unsigned char array[8];
    memset(array, 255, 8);
    printArray(array, 8);
    scanf("%hhu", array);
    printArray(array, 8);
    return 0;
}

muestra que scanf interpreta “%hhu” como “%u”. Está ignorando directamente el “hh”. La salida del código con la entrada 1 es:

255 255 255 255 255 255 255 255
1 0 0 0 255 255 255 255

  • está imprimiendo un char con un especificador para unsigned char UB?

    usuario1944441

    5 de abril de 2013 a las 3:11

  • @Armin char no está firmado de forma predeterminada, ¿no?

    –Daniel Castro

    5 de abril de 2013 a las 3:15

  • No, depende de la plataforma. No puedo reproducir tus resultados.

    usuario1944441

    5 de abril de 2013 a las 3:18

  • @Armin ¿Qué otros detalles serían útiles? Estoy usando Windows. No he tocado los argumentos predeterminados para GCC en CodeBlocks. Por cierto, declarar explícitamente las variables como caracteres sin firmar no resuelve mi problema: S

    –Daniel Castro

    5 de abril de 2013 a las 3:21


  • Aunque el tema es similar al duplicado propuesto, la discusión aquí es mejor que la discusión en el duplicado; en particular, la respuesta aquí destaca que el tiempo de ejecución de MSVC es C89 y no C99, por lo que usar una notación C99 no funciona de manera confiable.

    –Jonathan Leffler

    5 abr 2013 a las 23:05

El detalle importante es que está utilizando Windows y, presumiblemente, un entorno C obsoleto o no conforme (compilador y biblioteca estándar). MSVCRT solo es compatible con C89 (e incluso entonces, no del todo correctamente); en particular, no había modificador “hh” en C89, y probablemente esté interpretando “hh” igual que “h” (es decir, short).

  • Cambiar todo %hhu a %hu se imprimió exactamente como se publicó en OP.

    usuario1944441

    5 de abril de 2013 a las 3:25

  • Esto es más un problema de la biblioteca estándar que del compilador. Si el gcc de OP está usando MSVCRT (que será el caso si es “mingw”), entonces este es definitivamente el problema. Si desea hacer C moderno en Windows, la única opción viable en este momento es Cygwin.

    – R.. GitHub DEJA DE AYUDAR A ICE

    5 de abril de 2013 a las 3:26


  • Creo que el paquete CodeBlocks usa MinGW. No tengo ningún problema en cambiar o actualizar mi entorno, solo tengo curiosidad acerca de este comportamiento. ¿Debo suponer que es un error?

    –Daniel Castro

    5 de abril de 2013 a las 3:30

  • @DanielCastro: Es solo que la biblioteca estándar de Microsoft C que proporciona su scanf() solo es compatible con C89, que no incluye el hh modificador

    – café

    5 de abril de 2013 a las 3:35

  • Solo para aclarar. Creo que me equivoqué en algunas pruebas antes. El uso de %hu con caracteres sin firmar*, aunque UB, sobrescribe dos bytes como era de esperar. MSVCRT interpreta %hhu como %u.

    –Daniel Castro

    12 de abril de 2013 a las 2:40

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad