%。在s中的printf语句中的#s格式说明符

时间:2013-08-30 07:09:50

标签: c string printf format-specifiers

请解释输出。 %.#s中的printf()是什么意思?

#include<stdio.h>
#include <stdlib.h>

int main(int argc,char*argv[]){

    char *A="HELLO";
    printf("%.#s %.2s\n",A,A);
    return 0;
}

输出:

#s HE

3 个答案:

答案 0 :(得分:5)

这是未定义的行为。 #格式说明符中的printf表示替代表单,但根据标准,#仅与oaA一起使用,xXeEfFgG,包括s

  

C11§7.21.6.1 fprintf函数第6节

     

#结果转换为“替代形式”。对于o转换,它会增加   精度,当且仅在必要时,强制结果的第一个数字为a   零(如果值和精度都是0,则打印单个0。对于x(或X)   转换时,非零结果的前缀为0x(或0X)。对于aAeEfFgG次转化,总是转换浮点数的结果   包含小数点字符,即使后面没有数字。 (通常,只有在跟随数字后,才会在这些转换的结果中显示小数点字符。)对于gG次转换,不会从结果中删除尾随零。对于其他转换,行为未定义。

例如,在我的机器上,输出不同:%.0#s HE

答案 1 :(得分:3)

%.1s用于打印字符串的第一个字符

%.2s用于打印字符串的前两个字符

%.3s用于打印字符串的前三个字符,依此类推

其中#:执行转换的替代形式标记,可选择使用{{1}中的格式参数}}和printf()函数等。

但正如@Yu Hao所说,fprintf()仅与#oaAx一起使用,{ {1}},XeEfF,不包括g

在你的情况下G使用是错误的。

@WhozCraig给出的参考用法示例:

s

答案 2 :(得分:1)

我同意余浩的回答,认为这是不确定的行为,但我认为原因是不同的。是的,#字符用作将结果转换为替代格式的标志。是的,#标志未定义为字符串。但在这种情况下,#不是一个标志,它是一个精度。它仍然未定义,但原因是不同的

§6.21.6.1中的C11标准表示%符号遵循顺序

  1. 零个或多个标志(包括#
  2. 可选的最小字段宽度
  3. 可选的精度
  4. 可选长度修饰符
  5. 转换说明符字符
  6. 除转换说明符外,这些都是可选的。但它们出现的顺序始终如上所述。因此,如果存在,则必须是%字符后面的第一个标记。在%之后的内容不是表示标志的东西,它是句点:%.,表示精度。

    如果%.#的格式字符串中有printf(),则句点表示后面的字符是后面的转换规范的精度。即,代码中的#指定字符串s精度,而不是标志。要成为一面旗帜,必须直接遵循%字符,而不需要介入时间。

    关于精度,C标准§7.21.6.1说明了这一点:

    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.
    

    由于您的格式字符串中包含%.#s,而#既不是an asterisk *也不是decimal integer,因此结果未定义。

    因此,要非常准确地说明为什么您的代码未定义,我认为这是因为#字符代替了合法精度,而不是因为它是%s转换的非法标志。当然,作为一面旗帜是非法的,但这不是恰恰(har har)在这里发生的事情。