请解释输出。 %.#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
答案 0 :(得分:5)
这是未定义的行为。 #
格式说明符中的printf
表示替代表单,但根据标准,#
仅与o
,a
,A
一起使用,x
,X
,e
,E
,f
,F
,g
,G
,包括s
。
C11§7.21.6.1
fprintf
函数第6节
#
结果转换为“替代形式”。对于o
转换,它会增加 精度,当且仅在必要时,强制结果的第一个数字为a 零(如果值和精度都是0
,则打印单个0
。对于x
(或X
) 转换时,非零结果的前缀为0x
(或0X
)。对于a
,A
,e
,E
,f
,F
,g
和G
次转化,总是转换浮点数的结果 包含小数点字符,即使后面没有数字。 (通常,只有在跟随数字后,才会在这些转换的结果中显示小数点字符。)对于g
和G
次转换,不会从结果中删除尾随零。对于其他转换,行为未定义。
例如,在我的机器上,输出不同:%.0#s HE
答案 1 :(得分:3)
%.1s
用于打印字符串的第一个字符
%.2s
用于打印字符串的前两个字符
%.3s
用于打印字符串的前三个字符,依此类推
其中#:执行转换的替代形式是标记,可选择使用{{1}中的格式参数}}和printf()
函数等。
但正如@Yu Hao所说,fprintf()
仅与#
,o
,a
,A
,x
一起使用,{ {1}},X
,e
,E
,f
,F
,不包括g
。
在你的情况下G
使用是错误的。
@WhozCraig给出的参考用法示例:
s
答案 2 :(得分:1)
我同意余浩的回答,认为这是不确定的行为,但我认为原因是不同的。是的,#
字符用作将结果转换为替代格式的标志。是的,#
标志未定义为字符串。但在这种情况下,#
不是一个标志,它是一个精度。它仍然未定义,但原因是不同的
§6.21.6.1中的C11标准表示%
符号遵循顺序:
#
)除转换说明符外,这些都是可选的。但它们出现的顺序始终如上所述。因此,如果存在,则必须是%
字符后面的第一个标记。在%
之后的内容不是表示标志的东西,它是句点:%.
,表示精度。
如果%.#
的格式字符串中有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)在这里发生的事情。