cancel
Showing results for 
Search instead for 
Did you mean: 

In CubeIDE, Can scanf() read an 8 character hexadecimal value, or is this a known bug?

LCott.1
Associate II

When I attempt to read an 8 character hexadecimal value with sscanf(), I get 0x7FFFFFFF for all values over "80000000". It's as if sscanf() is confusing signed and unsigned numbers. If I read the 8 characters as two sets of 4, there is no problem (this is my workaround). If I try this scaled down to 16 bits, there is no problem. If I put this same code in visual studio (with sscanf deprecation disabled), there is no problem. I'm just using "include <stdio.h>" to get sscanf() as it ships with CubeIDE.

The attached code snippet is for illustration. It only take lines 13-15 or 19-21 to recreate the problem.

int size32=sizeof(unsigned int);	//just to verify data sizes
    int size16=sizeof(unsigned short);	//just to verify data sizes
 
    //need to read in 8 characters as a 32 bit hex value
    char str1[]="12345678";
    unsigned int val1;
    int res1=sscanf(str1,"%8X",&val1);
 
    char str2[]="7F123456";
    unsigned int val2;
    int res2=sscanf(str2,"%8X",&val2);
 
    char str3[]="80123456";
    unsigned int val3;
    int res3=sscanf(str3,"%8X",&val3);
    //val3 should be 0x80123456, but sscanf returns 0x7FFFFFFF
    //THIS is the issue of this post
 
    char str4[]="FEDCBA98";
    unsigned int val4;
    int res4=sscanf(str4,"%8X",&val4);
    //val4 should be 0xFEDCBA98, but sscanf returns 0x7FFFFFFF
    //THIS is the issue of this post
 
    unsigned int val5,val6;
    int res5=sscanf(str4,"%4X%4X",&val5,&val6);
    unsigned int val7=(val5<<16)+val6;
    //scanned as separate 4+4 chars instead of 8, no problem
 
    //trying the same thing scaled down to 16 bits
    char str10[]="1234";
    unsigned short val10;
    int res10=sscanf(str10,"%4hX",&val10);
 
    char str11[]="FEDC";
    unsigned short val11;
    int res11=sscanf(str11,"%4hX",&val11);

0693W00000bhR15QAE.png

13 REPLIES 13

I believe this is an unintended "mild bug":

number:

scan_data.code = (c < 'o') ? CT_INT : CT_UINT;

The intention of this line is to elegantly separate those format characters out of the "number-specific" characters (pxXduio) which are signed - basically d and i - and unintentionally it included X too.

I'm not interested in <stdio.h> and not going to report it to the newlib crew, feel free to do that whoever feels like it.

JW

[EDIT] And here's the culprit https://sourceware.org/git/?p=newlib-cygwin.git;a=commitdiff;h=7c9651e3ccea4f8bbc5fe50d0ed266f8976a3328

> 64 bit sscanf doesn't work at all ("%8llx" or "%llx").

Yes, the newlib "nano" variant does not support 64-bit long long formats (ll) and simply skips the format element. Yes this looks and feels like a bug.

No support for long long is a documented feature of nano (as far as nano is documented at all) - it's the price you pay for it being nano, the same as the hassle with floats etc. print()/scanf() and kin are very expensive and nano was a motion to find some middle ground for those mcus where kilobyte matters.

Different behaviour for X and x is a genuine bug.

JW

@Jan the bug here is how it handles the formats with ll. It treats them as completely unknown. It could at least return error (-1) or call error handler (abort...) to alert the developer early. But this is "mild".

The other bug that you've found is IMHO a terrible one. That kind that causes epic things like spacecraft explosions.