Why only multiple "%" is accepted by printf? - c

Following program give the output %%. Why?
#include <stdio.h>
int main() {
//code
printf("%%%%");
return 0;
}
output:
%%

TL;DR a % is a valid conversion specifier for printf().
Quoting C11, chapter §7.21.6.1, for conversion specifiers,
Each conversion specification is introduced by the character %. After the %, the following
appear in sequence:
.....
— A conversion specifier character that specifies the type of conversion to be applied.
and, from paragraph 8, for % as a conversion specifier character
for % conversion specifier
% A % character is written. No argument is converted. The complete
conversion specification shall be %%.
Your code has a pair of %%s.

Printf function's first argument is a format represented by a char*, it's not a string.
That's why for printing an int,for example, you have to write "%d". So % is a special character, if you only write % as format, the compiler won't be happy because it is waiting for something after the % (either d, p, x, s, f, ...).
However, by writing %% it means "Print me one escaped %". That's why %%%% prints %%
EDIT: If you want a function that prints exactly what you give, you can use write:
char* mystr = "%%%%";
write(STDOUT_FILENO, mystr, strlen(mystr));

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|.

Why % gets printed in half count in C?

#include<stdio.h>
main()
{
printf("% % % %");
}
For the above program, the output is % %. But why? (I used gcc compiler).
Undefined behavior is invoked by using invalid format specifier.
N1570 7.21.6.1 The fprintf function says in the description of % conversion specifier:
The complete conversion specification shall be %%.
N1570 4. Conformance says:
If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined.
The description of % conversion specifier is in "Description" section, not constraint nor runtime-constraint section.
In the actual implemention, the system's behavior seems like this:
Read first % and start parsing specifier
Read and save it as a flag
Read second % and treat it as % conversion specifier
Read after that and print it because it is not a part of specifier
Read % % and do work like 1-3
That is interesting. the % % counts as %% somehow, huh. Must be in the parsing rules for printf formats in the stdio library. In general "% " is not exactly a valid format specification. %% %% %% %% would get you what you want.

understanding weird output of printf function

According to me
int a=0;
printf("%d",a);
works same as
char *ptr="%d"
ptr points to % and then ptr reads the whole string from % and 4 bytes are read from memory.
Now consider the below code
printf("%d"+1,a); //value of a=0
is same as
char *ptr="%d"
ptr+=1;
ptr now points to d and so string from d is printed
Now
printf(1+"Alex"); //prints lex
ptr points l and prints string from there on....
Now what will happen in the following cases?It appears to be out of my scope.
printf("%",a);
printf("%%%%");
printf("%%d",a);
printf("%",a); does not have a valid conversion specifier, so it is covered by:
§7.21.6.1
9 If a conversion specification is invalid, the behavior is
undefined. If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.
printf("%%%%"); will simply print %%, since %% is a conversion specifier. See the printf man pages.
%
A '%' is written. No argument is converted. The complete conversion
specification is '%%'.
As mentioned in the comments, printf("%%d",a); is probably not undefined behavior. %% becomes % and the a is ignored.
§7.21.6.1
2 The fprintf function writes output to the stream pointed to by stream,
under control of the string pointed to by format that specifies how
subsequent arguments are converted for output. If there are
insufficient arguments for the format, the behavior is undefined. If
the format is exhausted while arguments remain, the excess arguments
are evaluated (as always) but are otherwise ignored. The fprintf
function returns when the end of the format string is encountered.
I hope that this quote from the C Standard will help you
8 The conversion specifiers and their meanings are:
% A % character is written. No argument is converted. The complete
conversion specification shall be %%.
For example
printf("%%%%");
will output
%%

How integers numbers are printed with %f specifier? [duplicate]

This question already has answers here:
Unexpected output of printf
(4 answers)
Closed 9 years ago.
#include<stdio.h>
main()
{
int a = 66;
printf("%f", a);
}
It is printing 0.0000 as an answer, why?
And %f is replaced with %c it is printing B. I am not getting the reason.
Please explain !!
It is because your program invokes undefined behavior. You may get anything, either expected or unexpected.
C11: 7.29.2 Formatted wide character input/output functions:
If a conversion specification is invalid, the behavior is undefined.335) If any argument is not the correct type for the corresponding conversion specification, the behavior is
undefined.
printf("%f",a);
^ %f specifier expects arguments of type float/ double.
And %f is replaced with %c it is printing B. I am not getting the reason
ASCII code of character B is 66. Using %c specifier prints the (printable) character itself.
For printf():
[...] If any argument is not the type expected by the corresponding conversion specifier, or if there are less arguments than required by format, the behavior is undefined. If there are more arguments than required by format, the extraneous arguments are evaluated and ignored [...]
Although, for %c, you correctly get the expected 'B' (whose ASCII code is 66), it is not recommended (imaging when you pass in 666, which will get unexpected result as no ASCII code is 666). At least, you should do type-casting beforehand:
printf("%f", (float)a);
printf("%c", (char)a);
Again, remember always use the corresponding specifiers for different types.
If you use %f specifier and do not provide a float number, but int, the behaviour is undefined. In practice the memory starting in the location where your int is will be interpreted as float number, so what gets printed depends on internal representation of ints and floats.
For %c you got B since %c interprets your int as character code, and B's code is 66.
%f is used to print floating point number
%c is used to print character
%d is used to print integer number
so when you are using %c printf function converting from ascii value to character of B.
if you want to print the integer
printf("%d",a);
%c prints the character corresponding to 66 into ascii table.
By default %f will print 5 digits after the decimal point, but you can change the behaviour with %.3f (for 3 digits)

%.#s format specifier in printf statement in c

Please explain the output. What does %.#s in printf() mean?
#include<stdio.h>
#include <stdlib.h>
int main(int argc,char*argv[]){
char *A="HELLO";
printf("%.#s %.2s\n",A,A);
return 0;
}
OUTPUT:
#s HE
It's undefined behavior. # in printf format specifier means alternative form, but according to the standard, # is only used together with o, a, A, x, X, e, E, f, F, g, G, not including s.
C11 §7.21.6.1 The fprintf function Section 6
# The result is converted to an ‘‘alternative form’’. For o conversion, it increases
the precision, if and only if necessary, to force the first digit of the result to be a
zero (if the value and precision are both 0, a single 0 is printed). For x (or X)
conversion, a nonzero result has 0x (or 0X) prefixed to it. For a, A, e, E, f, F, g, and G conversions, the result of converting a floating-point number always
contains a decimal-point character, even if no digits follow it. (Normally, a decimal-point character appears in the result of these conversions only if a digit follows it.) For g and G conversions, trailing zeros are not removed from the result. For other conversions, the behavior is undefined.
For example, on my machine, output is different: %.0#s HE
%.1s is used to print the first character of the string
%.2s is used to print the first two characters of the string
%.3s is used to print the first three characters of the string and so on
where # : alternative form of the conversion is performed is a flag which have an optional usage with the format parameter in printf() and fprintf() functions etc.
But as #Yu Hao said # is only used together with o, a, A, x, X, e, E, f, F, g, G, not including s.
in your case %.#s usage is Wrong.
Example usage from reference given by #WhozCraig :
printf("Hexadecimal:\t%x %x %X %#x\n", 5, 10, 10, 6);
printf("Octal:\t%o %#o %#o\n", 10, 10, 4);
I agree with Yu Hao's answer that it is undefined behavior, but I think the reason is different. Yes, the # character works as a flag to convert the result to an alternative format. Yes, the # flag is undefined for strings. But in this case, the # is not a flag, it's a precision. It's still undefined, but the reason is different
The C11 standard at §6.21.6.1 says that the % sign is followed in sequence by:
Zero or more flags (including #)
An optional minimum field width
An optional precision
An optional length modifier
A conversion specifier character
Except for the conversion specifier, these are all optional. But the order in which they appear is always as above. So flag, if present, has to be first, immediately after the % character. Here what follows the % is not something indicating a flag, it is a period: %., indicating precision.
When you have %.# in your format string for printf(), the period indicates that the following character is the precision for the conversion specification that follows. I.e., the # in your code specifies the precision for the string s, not a flag. To be a flag, it would have to directly follow the % character, without the intervening period.
With regard to precision, the C standard §7.21.6.1 says this:
The precision takes the form of a period (.) followed either by an asterisk *
(described later) or by an optional decimal integer; if only the period is specified,
the precision is taken as zero. If a precision appears with any other conversion
specifier, the behavior is undefined.
Since in your format string you have %.#s, and # is neither an asterisk * nor a decimal integer, the result is undefined.
So to be extremely exact about why your code is undefined, I think it's because the # character appears in place of a legal precision, not because it is an illegal flag for the %s conversion. It would be illegal as a flag, of course, but that's not what is precisely (har har) happening here.

Resources