Question

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
Was it helpful?

Solution

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

OTHER TIPS

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

  1. Zero or more flags (including #)
  2. An optional minimum field width
  3. An optional precision
  4. An optional length modifier
  5. 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top