scanf read integer input into uint8_t

Viewed 4806

Is there a way to use scanf to read an unsigned char decimal input into a uint8_t variable?

I am afraid if I read %hu or %u into a uint8_t, it may corrupt the adjacent memory because uint8_t is one byte, but %hu is 2 bytes, and %u is 4 bytes.

I am using MinGW32

gcc.exe (GCC) 4.9.3
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

The code I am worried about:

/* worried.c - issue demo code. */
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main(int argc, char **argv)
{
    uint8_t filler1 = 17;             /* do not corrupt me please. */
    uint8_t my_mem;
    uint8_t filler2 = 39;             /* do not corrupt me please. */ 

    printf("please enter a number: $ ");
    scanf("%u", &my_mem);             /* corrupts fillers... */
    // scanf("%hu", &my_mem);         /* this also corrupts... */
    // scanf("%hhu", &my_mem);        /* still corrupts... */ 
    // scanf("%"SCNu8, &my_mem);      /* still corrupts... */
    // scanf("%"PRIu8 "\n", &my_mem); /* still corrupts... */

    printf("filler1 = %u.\n", filler1);
    printf("my_mem = %u.\n", my_mem);
    printf("filler2 = %u.\n", filler2);         

    return 0;
}

Note that the code above does corrupt the fillers, which is catastrophic when reading into a struct which is going to be directly written into a binary(record) file later.

I could solve it by casting from a temporary variable, but that takes a little extra work for my program which I was wondering if I could avoid forcing my program to do, and read into my_mem directly.

To date, it seems the solution that seems most likely is:

The only way to portably do this that works on GCC4.9.3 and newer is through casting. There are more elegant solutions on GCC5.2 e.g. %hhu, but they misbehave on GCC4.9.3.

2 Answers
Related