2023-04-03 01:59 PM
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);
Solved! Go to Solution.
2023-04-05 12:33 AM
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
2023-04-05 05:10 AM
> 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.
2023-04-05 07:39 AM
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
2023-04-05 09:52 AM
@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.