简体   繁体   中英

Why does sscanf result in 0 in this case?

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), "%04hhx", a);
    snprintf(bStr, sizeof(bStr), "%04x", b & 0xFFFF);
    snprintf(cStr, sizeof(cStr), "%08hhx", c);
    snprintf(dStr, sizeof(aStr), "%08x", 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, "%04hhx", &aOut);
    sscanf(bStr, "%04x", &bOut);
    sscanf(cStr, "%08hhx", &cOut);
    sscanf(dStr, "%08x", &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?

The line

sscanf(aStr, "%04hhx", &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, "%04"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, "%04x", &bOut);
sscanf(cStr, "%08hhx", &cOut);
sscanf(dStr, "%08x", &dOut);

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

sscanf(bStr, "%04"SCNx16, &bOut);
sscanf(cStr, "%08"SCNx32, &cOut);
sscanf(dStr, "%08"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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM