Search code examples
c++printfvariadic-functions

is an argument of type long OK for %x printf specifier?


I found this on Win32 docs:

// Check the smart card context handle.
// hContext was set previously by SCardEstablishContext.

LONG    lReturn;
lReturn = SCardIsValidContext(hContext);
if ( SCARD_S_SUCCESS != lReturn )
{
   // Function failed; check return value.
   if ( ERROR_INVALID_HANDLE == lReturn )
       printf("Handle is invalid\n");
   else
   {
       // Some unexpected error occurred; report and bail out.
       printf("Failed SCardIsValidContext - %x\n", lReturn);
       exit(1);  // Or other appropriate error action.
   }
}
else
{
   // Handle is valid; proceed as needed.
   // ...
}

The printf("Failed SCardIsValidContext - %x\n", lReturn); line is passing an argument of type LONG (typedef for long) to printf where printf expects unsigned int according to cppreference.com. Is this well defined behavior? If so, is it the same as an explicit static_cast to unsigned int?


Solution

  • is an argument of type long OK for %x printf specifier?

    No, it is not OK in C++. %x is for unsigned int, not for long.

    Is this well defined behavior?

    No, this is undefined behaviour. Quote from C standard draft (which is where the format specifiers are defined):

    x,X The unsigned int argument is converted to ... unsigned hexadecimal notation ...

    If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.


    It may be "OK" in windows if the system documents so, but relying on such guarantee will not be portable to other systems. I suspect that the example is not intended as documentation of validity of such misuse of format specifier, but that it is accidental.