Home > OS >  Why does sscanf result in 0 in this case?
Why does sscanf result in 0 in this case?

Time:09-21

I am trying to convert a series of decimal numbers to their hex representation in string format and then back from string to decimal. This might sound strange but is a simplified representation of a more complex situation. So, either way, I have the following piece of code which almost works fine. For some reason my variable a is still equal to 0 at the end while it should equal 43, all the other variables seem to be alright:

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    /********************* A *******************/
    uint16_t a = 43;   //0x002b 
    int16_t  b = -43;  //0xffd5
    uint32_t c = 234;  //0x000000ea
    int32_t d = -234;  //0xffffff16

    char aStr[10]={0};
    char bStr[10]={0};
    char cStr[10]={0};
    char dStr[10]={0};

    snprintf(aStr, sizeof(aStr), "hhx", a);
    snprintf(bStr, sizeof(bStr), "x", b & 0xFFFF);
    snprintf(cStr, sizeof(cStr), "hhx", c);
    snprintf(dStr, sizeof(aStr), "x", d & 0xFFFFFFFF);

    fprintf(stdout, "TX a = %s.\n", aStr);
    fprintf(stdout, "TX b = %s.\n", bStr);
    fprintf(stdout, "TX c = %s.\n", cStr);
    fprintf(stdout, "TX d = %s.\n", dStr);

    /********************* B *******************/

    uint16_t aOut = 0;
    int16_t bOut = 0;
    uint32_t cOut = 0;
    int32_t dOut = 0;

    sscanf(aStr, "hhx", &aOut);
    sscanf(bStr, "x", &bOut);
    sscanf(cStr, "hhx", &cOut);
    sscanf(dStr, "x", &dOut);

    fprintf(stdout, "rx a = %d\n", aOut);  //<---- this line prints 0 for a. Why?
    fprintf(stdout, "rx b = %d\n", bOut);
    fprintf(stdout, "rx c = %d\n", cOut);
    fprintf(stdout, "rx d = %d\n", dOut);

    return 0;
}

Does anybody know why or what I am missing?

CodePudding user response:

The line

sscanf(aStr, "hhx", &aOut);

is wrong. The %hhx conversion format specifier requires an argument of type unsigned char *, but you are instead passing it an argument of type uint16_t *. This invokes undefined behavior.

I suggest that you change that line to the following:

sscanf(aStr, ""SCNx16, &aOut);

On most platforms, the macro SCNx16 will simply expand to "hx", but it is generally safer to use the macro, in case you code happens to be running on a (future) platform on which uint16_t is not equivalent to an unsigned short.

The lines

sscanf(bStr, "x", &bOut);
sscanf(cStr, "hhx", &cOut);
sscanf(dStr, "x", &dOut);

are also using the wrong conversion format specifiers. I recommend that you use the following code instead:

sscanf(bStr, ""SCNx16, &bOut);
sscanf(cStr, ""SCNx32, &cOut);
sscanf(dStr, ""SCNx32, &dOut);

Strictly speaking, the above code also invokes undefined behavior, because the %x conversion format specifier requires a pointer to an unsigned type instead of to a signed type. However, this should not be a problem in practice, provided that the converted value can be represented both in the signed type and in the unsigned type.

  •  Tags:  
  • c
  • Related