请解释输出。%.#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
请解释输出。%.#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
这是未定义的行为。#
in printf
format specifier 表示替代形式,但根据标准,#
仅与o
, a
, A
, x
, X
, e
, E
, f
, F
, g
,一起使用G
,不包括s
.
C11 §7.21.6.1功能第
fprintf
6 节
#
结果将转换为“替代形式”。对于o
转换,当且仅在必要时,它会增加精度,以强制结果的第一个数字为零(如果值和精度都是0
,0
则打印一个)。对于x
(orX
) 转换,非零结果具有0x
(or0X
) 前缀。对于a
,A
,e
,E
,f
,F
,g
, 和G
转换,浮点数的转换结果总是包含一个小数点字符,即使它后面没有数字。(通常,小数点字符仅在其后有数字时才会出现在这些转换的结果中。)对于g
和G
转换,尾随零不会从结果中删除。对于其他转换,行为未定义。
例如,在我的机器上,输出是不同的: %.0#s HE
%.1s
用于打印字符串的第一个字符
%.2s
用于打印字符串的前两个字符
%.3s
用于打印字符串的前三个字符等等
其中 # :执行转换的替代形式是一个标志,它与格式参数printf()
和fprintf()
函数等 具有可选用法。
但正如@Yu Hao所说#
,仅与o
, a
, A
, x
, X
, e
, E
, f
, F
, g
,一起使用G
,不包括s
.
在您的情况下,%.#s
用法是错误的。
@WhozCraig 给出的参考示例用法:
printf("Hexadecimal:\t%x %x %X %#x\n", 5, 10, 10, 6);
printf("Octal:\t%o %#o %#o\n", 10, 10, 4);
我同意于浩的回答是未定义的行为,但我认为原因不同。是的,该#
字符用作将结果转换为替代格式的标志。是的,该#
标志对于字符串是未定义的。但在这种情况下,这#
不是一个标志,而是一个精度。它仍然未定义,但原因不同
§6.21.6.1 中的 C11 标准说,该%
符号后面依次是:
#
)除了转换说明符,这些都是可选的。但它们出现的顺序始终如上。因此,如果存在 flag,则必须位于第一个,紧跟在%
字符之后。这里后面的%
不是表示标志的东西,而是句点:%.
,表示精度。
当您%.#
的格式字符串中有 forprintf()
时,句点表示后面的字符是后面转换规范的精度。即,#
您的代码中的 指定string的精度s
,而不是flag。要成为一面旗帜,它必须直接跟随%
角色,没有中间时间。
关于精度,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 *
也不是 a decimal integer
,所以结果是未定义的。
因此,要非常准确地说明您的代码未定义的原因,我认为这是因为该#
字符出现在合法精度的位置,而不是因为它是%s
转换的非法标志。当然,它作为旗帜是非法的,但这并不是(har har)在这里发生的事情。