printf: why doesn't %x print leading 0x (as opposed to %a)? - c

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)

"%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 ---------^^^^^^^^

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.

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

Related

Can anyone explain the output printf("%0 %x",a);?

This code is making me so confused. I can't understand what %0 is doing inside printf!
Code:
#include <stdio.h>
int main() {
int a = 100;
printf("%0 %x", a);
return 0;
}
Output
%x
%0 %x has an invalid printf conversion specification:
the 0 is a flag specifying that the number representation should be padded with initial zeroes to the specified width (which is not specified here)
the is a flag specifying that the signed conversion should be prefixed with a space if positive in the same place as a - for negative numbers.
the second % is the conversion specifier, so the initial part is just a variation of %% with 2 extra flags and thus should cause a % character to be output, but the C Standard specifies in 7.21.6.20 the fprintf function that
%: A % character is written. No argument is converted. The complete conversion specification shall be %%.
Hence %0 % is an invalid conversion specification as % does not accept flags.
Most libraries will just output %x, ie: % for %0 % and x for the trailing x, ignoring the a argument, and this is what you get on your system, but the behavior is actually undefined, so nothing can be assumed.
Conversely, printf("|%0 5d|", 100); will output | 0100| but the space is ignored for the x conversion which is unsigned so printf("|%0 5x|", 100); will output |00064|.

Printing 0 in the place of blank space while using %5d in C [duplicate]

I have a floating point number such as 4917.24. I'd like to print it to always have five characters before the decimal point, with leading zeros, and then three digits after the decimal place.
I tried printf("%05.3f", n) on the embedded system I'm using, but it prints *****. Do I have the format specifier correct?
Your format specifier is incorrect. From the printf() man page on my machine:
0 A zero '0' character indicating that zero-padding should be used rather than blank-padding. A '-' overrides a '0' if both are used;
Field Width:
An optional digit string specifying a field width; if the output string has fewer characters than the field width it will be blank-padded on the left (or right, if the left-adjustment indicator has been given) to make up the field width (note that a leading zero is a flag, but an embedded zero is part of a field width);
Precision: An optional period, '.', followed by an optional digit string giving a precision which specifies the number of digits to appear after the decimal point, for e and f formats, or the maximum number of characters to be printed from a string; if the digit string is missing, the precision is treated as zero;
For your case, your format would be %09.3f:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("%09.3f\n", 4917.24);
return 0;
}
Output:
$ make testapp
cc testapp.c -o testapp
$ ./testapp
04917.240
Note that this answer is conditional on your embedded system having a printf() implementation that is standard-compliant for these details - many embedded environments do not have such an implementation.

'printf' with leading zeros in C

I have a floating point number such as 4917.24. I'd like to print it to always have five characters before the decimal point, with leading zeros, and then three digits after the decimal place.
I tried printf("%05.3f", n) on the embedded system I'm using, but it prints *****. Do I have the format specifier correct?
Your format specifier is incorrect. From the printf() man page on my machine:
0 A zero '0' character indicating that zero-padding should be used rather than blank-padding. A '-' overrides a '0' if both are used;
Field Width:
An optional digit string specifying a field width; if the output string has fewer characters than the field width it will be blank-padded on the left (or right, if the left-adjustment indicator has been given) to make up the field width (note that a leading zero is a flag, but an embedded zero is part of a field width);
Precision: An optional period, '.', followed by an optional digit string giving a precision which specifies the number of digits to appear after the decimal point, for e and f formats, or the maximum number of characters to be printed from a string; if the digit string is missing, the precision is treated as zero;
For your case, your format would be %09.3f:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("%09.3f\n", 4917.24);
return 0;
}
Output:
$ make testapp
cc testapp.c -o testapp
$ ./testapp
04917.240
Note that this answer is conditional on your embedded system having a printf() implementation that is standard-compliant for these details - many embedded environments do not have such an implementation.

why does following printf print 0x32

#include<stdio.h>
int main ()
{
printf("%#04x",50);
}
Some one showed me above code and I could not understand it since I do have used printf in C programs but above sort of use I saw in my life for the first time.
Why did above code prints output as
0x32
Can some one give me a link or reference to some thing so that I can understand it better.
From the printf(3) manual page:
The flag characters
The character % is followed by zero or more of the following flags:
# — The value should be converted to an "alternate form". For o conversions, the first character of the output string is made zero (by prefixing a 0 if it was not zero already). For x and X conversions, a nonzero result has the string "0x" (or "0X" for X conversions) prepended to it. For a, A, e, E, f, F, g, and G conversions, the result will always contain a decimal point, even if no digits follow it (normally, a decimal point appears in the results of those conversions only if a digit follows). For g and G conversions, trailing zeros are not removed from the result as they would otherwise be. For other conversions, the result is undefined.
Other flags omitted...
Thus, %# prepends "0x" to the output since the output format is x. The 0 is there to use 0 (zeros) for padding. Then the number 4 says the total number of characters to print is four. Had the number 4 been exchanged with 10, the output would have been 0x00000032 – a total of 10 characters.
50 decimal is 32 hexadecimal.
Apart from that, the documentation should tell you all you need to know.
Because %x formats the given value into hexadecimal.
In facts, 0x32 (hex) == 50 (decimal).
This is a good primer for reference.

Why does "%.3i" print leading zeros?

There was a bit of a surprise with some code today. I was compiling it on AIX, with the warning level set to anal to see what rogue issues might be lurking. Something new crawled out of the code.
1540-2837 (W) '0' flag is disregarded when combined with
precision and 'i' printf format.
After looking at the offending line, I put together a little program to reproduce it. Testing it on several platforms showed that it is not AIX specific.
The first printf below mimics what was found in the program.
#include <stdio.h>
int main(void)
{
int x = 3;
printf("Format 0.3i <%0.3i>\n", x); // prints 003, and AIX does a warning
printf("Format .3i <%.3i>\n", x); // prints 003, with no warning
printf("Format 3i <%3i>\n", x); // prints 3, with no warning.
return 0;
}
Normally, if leading zeros were needed, a format of "03i" would do the job nicely.
What does "%.3i" really mean here?
Why does it have the behavior that it does?
.X, where x is a number means "print at least X" digits, so %.3i means print at least 3 digits. If the number is less than 100, it is left padded with zeros.
From a doc on printf
"For integer specifiers (d, i, o, u, x, X): precision specifies the minimum number of digits to be written. If the value to be written is shorter than this number, the result is padded with leading zeros. The value is not truncated even if the result is longer. A precision of 0 means that no character is written for the value 0."
There is another concept, "width" (e.g. "%3i") which causes a certain number of characters to be output (not necessarily digits, and the 0 specified is used to say that those characters should be 0s, as in "003" and not spaces, as in " 3")
From man 3 printf:
If a precision is given with a
numeric conversion (d, i, o, u, x, and
X), the 0 flag is ignored.
The . is specifying the precision and therefore the 0 is ignored. As to the "Why?" of it, you'd have to ask the authors of the C standard :)

Resources