1

This code:

#include <stdio.h>
int main(void)
{
    printf("%a\n", 1.0);
    printf("%x\n", 93);
}

outputs:

0x1p+0
5d

Why not 0x5d?

Does someone know the rationale?

Note: this question is not exactly the same since it is about %#x.

Reason of the question: for %x cannot always "feed it back to C in initializer":

$ cat t324.c
#include <stdio.h>
int main(void)
{
    printf(X);
}

$ gcc t324.c -DX="\"double x = %a;\", 10.0" && ./a.exe | gcc -xc - -c
<nothing>

$ gcc t324.c -DX="\"int x = %x;\", 10" && ./a.exe | gcc -xc - -c
<stdin>:1:9: error: ‘a’ undeclared here (not in a function)
TylerH
  • 20,799
  • 66
  • 75
  • 101
pmor
  • 5,392
  • 4
  • 17
  • 36
  • Error '"\"double x = %a;\n\""" does not relate to posted code. There is no `a`. Is the `%x` getting messed up with shell? – chux - Reinstate Monica Mar 14 '22 at 21:11
  • This is not a language-lawyer question (tags edited). No question or controversy has been raised about how the language specification should be interpreted. – John Bollinger Mar 14 '22 at 21:14
  • @chux-ReinstateMonica Yes, I want `10.0`, thanks! Updated. Tested on both on `bash 4.3.48(1)` (Linux) and `bash 4.4.12(3)` (Cygwin). – pmor Mar 14 '22 at 21:24
  • @JohnBollinger Indeed, this is not a language-lawyer question. – pmor Mar 14 '22 at 21:26
  • pmor, Is the first output still ``? Try adding `puts(X);` to see what code really is getting for the format in the `printf()`. – chux - Reinstate Monica Mar 14 '22 at 21:27
  • Note also that `printf` output generated with `%x` can absolutely be fed back correctly to C, provided that `scanf` with `%x` (or `%X`) is used to read it. – John Bollinger Mar 14 '22 at 21:31
  • @JohnBollinger Yes, of course. I've just forgotten to mention "in initializer". Added. – pmor Mar 14 '22 at 22:02

3 Answers3

3

"%a", "%A" leads with "0x", "0X" to help distinguish it from decimal output of "%f", "%e", "%g", "%F", ...
Note "%a" instead of say "%e", affect 2 parts, the prefix and the base letter: "0x" and "p" instead of "" and "e".
"%a" came along well after memory prices dropped.

"%x" leads without a prefix as often code needs to concatenate hex output as in printf("%08x%08x", a32, b32); It is trivial to prefix with "0x" then as in "0x%08x%08x". Not prefixing hex output as the default was certainly more common, back in the day (1970s) as every bytes costs.

Using # with "%x" as in "%#x" does not always prefix output. The prefix occurs (in the same case as digits) when the value is non-zero.

For clarity, I find a lower case x and uppercase hex digits useful.

//       v------ lower --------v
printf("0x%08X\n", 0u-1u); // 0xFFFFFFFF 
//           ^-- upper ---------^^^^^^^^
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Although it's certainly a valid use case for `%x`, I think concatenating mutliple outputs is a much more specific rationale than is necessary or appropriate. More generally speaking, sometimes you want the prefix and sometimes you don't. – John Bollinger Mar 14 '22 at 21:09
2

I think you just have option to have 0x or not. When you use %x, you receive the raw hexadecimal number. But when you use %#x, you receive the hex number with the 0x prefix. What you choose depends on situation.

Jack05
  • 31
  • 4
0

As explained by @Jack05, the '#' character makes the difference. The manual of printf explains the conversion:

Each conversion specification is introduced by the character %, and ends with a conversion specifier. In between there may be (in this order) zero or more flags, an optional minimum field width, an optional precision and an optional length modifier.
The overall syntax of a conversion specification is:

      %[$][flags][width][.precision][length modifier]conversion

If the flag character is set with '#', then:

For x and X conversions, a nonzero result has the string "0x" (or "0X" for X conversions) prepended to it.

For the 'a' or 'A' conversion,

the double argument is converted to hexadecimal notation (using the letters abcdef) in the style [-]0xh.hhhhp±d; for A conversion the prefix 0X, the letters ABCDEF

Rachid K.
  • 4,490
  • 3
  • 11
  • 30