0

The "hh" specifier was introduced in C99, and I am using this specifier in my code. (Code example to follow...) My compiler is GCC 3.3.2, my OS is Solaris 8, and my C library is SUNW libc v1.21. The "hh" specifier has no effect when this code runs. When I switch over to Solaris 10, GCC 3.4.6 and SUNW libc 1.23, the code functions as expected. I compiled with and without the "-std=c99" option, and it made no difference. My conclusion is that the SUNW libc 1.21 does not support this C99 feature. I guess my question is (1) why not? and (2) is there some way to find out whether a particular C library supports a particular C99 feature? Thank you!

The code is simple:

uint8_t* scanByte;
uint32_t uScratch;  
uint8_t  aByte;

strcpy(scanByte,"0xF9");
sscanf(scanByte,"%x",   &uScratch );
sscanf(scanByte,"%hhx", &aByte    );

printf("scanByte: %s   uScratch: %x   aByte: %x\n", scanByte, uScratch, aByte); 

Solaris 8 output:

scanByte: 0xF9   uScratch: f9   aByte: 0

Solaris 10 output:

scanByte: 0xF9   uScratch: f9   aByte: f9

UPDATE:

I have changed the code as follows, and re-run:

unsigned int uScratch;  
unsigned char aByte;    
int scanResult1;
int scanResult2;


unsigned char* scanByte;

scanByte=malloc(5);
strcpy(scanByte,"0xF9");  

scanResult1 = sscanf(scanByte,"%x", &uScratch );
printf("scanByte: %s   uScratch: %x   scanResult1: %d\n", scanByte, uScratch, scanResult1); 

scanResult2 = sscanf(scanByte,"%hhx", &aByte );
printf("scanByte: %s   uScratch: %x   scanResult2: %d\n", scanByte, uScratch, scanResult2);

Solaris 10 output:

scanByte: 0xF9   uScratch: f9   scanResult1: 1
scanByte: 0xF9   uScratch: f9   scanResult2: 1

Solaris 8 output:

scanByte: 0xF9   uScratch: f9   scanResult1: 1
scanByte: 0xF9   uScratch: f9   scanResult2: 0

So, yup, something about Solaris 8 + scanf + hhx, as I originally suspected. But my question stands: how does one determine whether a particular C99 feature is supported by libc? GCC 3.3.2 is a C99 compiler, but obviously the libc version doesn't fully support C99. How do I find out what C99 features are not supported?

2 Answers2

2

Functions such as sscanf() & sprintf() are implemented in the operating system C library (libc), not in the compiler, so it doesn't matter what the compiler supports when passing those arguments to the functions in libc. Solaris did not add C99 support to that library until Solaris 10 - Solaris 8 was released in February 2000, is thus now very old, about to end its support life, and not a good choice for trying to write C99 code.

alanc
  • 4,102
  • 21
  • 24
1

[Edit]
After sorting through minor issues of incorrect buffer initialization and format specifiers, the problem remains: a supposed C99 complier does not use "%hhx" in scanResult2 = sscanf(scanByte,"%hhx", &aByte ); as expected.

This same compiler also does not define the SCNx8 macro implying it does not know how to scanf() a uint8_t.

Suggest using this lack of macro definition to steer code in scanning unsigned char.

#include <inttypes.h>
...
unsigned char uc;
uint8_t u8;
#ifdef SCNx8
   cnt1 = sscanf(buf, "%hhx", &uc);
   cnt2 = sscanf(buf, "%" SCNx8, &u8);
#else
   unsigned un;
   cnt1 = sscanf(buf, "%2x", &un);
   uc = (unsigned char) un;
   cnt2 = sscanf(buf, "%2x", &un);
   u8 = (uint8_t) un;
#ednif

As @BLUEPIXY identified, uint8_t* scanByte; is not initialized.

// uint8_t* scanByte;
uint8_t* scanByte = malloc(5);
strcpy(scanByte,"0xF9");
// or
uint8_t* scanByte = "0xF9";

Also should not mix uint32_t with "%x" and uint8_t with "%hhx". Better to use SCNxn_t.

#include <inttypes.h>
sscanf(scanByte,"%" SCNx32,  &uScratch );
sscanf(scanByte,"%" SCNx8,   &aByte    );
printf("scanByte: %s   uScratch: %" PRIx32 "   aByte: %" PRIx8 "\n", 
    scanByte, uScratch, aByte); 

or standard tpyes

unsigned uScratch;  
unsigned char aByte;
sscanf(scanByte,"%x",   &uScratch );
sscanf(scanByte,"%hhx", &aByte    );
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Aren't the SCNxn macros guaranteed to correspond to the types in stdint.h? – Lundin Apr 02 '14 at 14:25
  • @Lundin Yes, but OP was not using correspond types. In all likelihood, on OP's system (and many others), they happened to correspond: (typically `unsigned char` the same as `uint8_t` and `unsigned` the same as `uint32_t`), but this is not guaranteed by spec. – chux - Reinstate Monica Apr 02 '14 at 14:37
  • Interesting... when I compile on Solaris 10 with GCC 3.3.2 I have no problem, but when I compile on Solaris 8 GCC 3.3.2 I get an error because the "SCNx8" macro isn't defined. Note that the above is not a typo. I compiled using GCC 3.3.2 on both operating systems. Furthermore, when I took my ORIGINAL code and compiled it with 3.3.2 on Solaris 10, everything worked. So I have now compiled on Solaris 10 using GCC 3.4.6 and 3.3.2, and both executables worked correctly. The problem is thus related to libc/Solaris 8, as I originally assumed. – user3489681 Apr 02 '14 at 15:18
  • @user3489681 `"SCNx8"` need not be define in C99dr as 7.8.1 Macros for format specifiers 6 "For each type that the implementation provides in , the corresponding fprintf macros shall be defined and the corresponding fscanf macros shall be defined unless the implementation does not have a suitable fscanf length modifier for the type." **This** lack of macro definition _might_ be usable by your code to hint `"hh"` is not available for `unsigned char` - but that may be a kludge. – chux - Reinstate Monica Apr 02 '14 at 15:30
  • @user3489681 Without the `SCNx8`, one cannot do `uint8_t aByte; sscanf(scanByte,"%" SCNx8, &aByte);` and code should not do `uint8_t aByte; sscanf(scanByte,"%hhx", &aByte);`. But things are fuzzy about the ability to do `unsigned char aByte; sscanf(scanByte,"%hhx", &aByte);`. – chux - Reinstate Monica Apr 02 '14 at 15:36
  • I looked at inttypes.h on my Solaris 8 vs Solaris 10 machine. The Solaris 8 one says it's tracking ISO/IEC 9899:1990, and Solaris 10 is tracking ISO/IEC 9899:1999. So there's my C90 versus C99, I guess! – user3489681 Apr 02 '14 at 15:57
  • @user3489681 Welcome to SO. Hope your initial post has not put you off for it looks like we eventually got to the core issue: "ISO/IEC 9899:1990". – chux - Reinstate Monica Apr 02 '14 at 16:01
  • Not put off in the least -- I wouldn't have looked at inttypes.h if it weren't for your suggestion to use the SCN macros. Thanks! – user3489681 Apr 02 '14 at 17:22