Reputation: 416
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
Upvotes: 5
Views: 7751
Reputation: 7917
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:
#
)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.
Upvotes: 1
Reputation: 10516
%.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);
Upvotes: 4
Reputation: 122373
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’’. Foro
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 both0
, a single0
is printed). Forx
(orX
) conversion, a nonzero result has0x
(or0X
) prefixed to it. Fora
,A
,e
,E
,f
,F
,g
, andG
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.) Forg
andG
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
Upvotes: 7