%c中printf语句中的.s格式说明符

%c中printf语句中的.s格式说明符,c,string,printf,format-specifiers,C,String,Printf,Format Specifiers,请解释输出。printf()中的%.#s是什么意思 #include<stdio.h> #include <stdlib.h> int main(int argc,char*argv[]){ char *A="HELLO"; printf("%.#s %.2s\n",A,A); return 0; } 这是未定义的行为在printf中,格式说明符表示替代形式,但根据标准,仅与o,a,a,x,x,e,e,f,g,,不包括s C11§7.21.6

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

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

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

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

这是未定义的行为<代码>在
printf
中,格式说明符表示替代形式,但根据标准,
仅与
o
a
a
x
x
e
e
f
g
,不包括
s

C11§7.21.6.1功能第6节
#
结果被转换为“替代形式”。对于
o
转换,它会增加 当且仅当必要时,强制结果的第一个数字为a的精度 零(如果值和精度均为
0
,则打印一个
0
)。对于
x
(或
x
) 转换时,非零结果的前缀为
0x
(或
0x
)。对于
a
a
e
e
f
f
g
g
转换,浮点数的转换结果始终为 包含小数点字符,即使后面没有数字。(通常,只有在转换结果后面有一个数字时,才会在转换结果中显示小数点字符。)对于
g
g
转换,不会从结果中删除尾随的零。对于其他转换,行为是未定义的


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

我同意余浩的回答,那是未定义的行为,但我认为原因不同。是的,
#
字符用作将结果转换为其他格式的标志。是,字符串的
#
标志未定义。但在本例中,
#
不是一个标志,而是一个精度。它仍然没有定义,但原因不同

§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
    #
    既不是
    星号*
    也不是
    十进制整数
    ,因此结果未定义


    因此,为了非常准确地解释代码未定义的原因,我认为这是因为
    #
    字符取代了合法精度,而不是因为它是
    %s
    转换的非法标志。作为一面旗帜当然是非法的,但这并不是这里发生的事情

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

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

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

    其中#:执行转换的替代形式是一个标志,它与
    printf()
    fprintf()
    函数等中的格式参数有可选用法

    但正如@Yu Hao所说的
    只与
    o
    a
    a
    x
    x
    e
    e
    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);
    

    上的文档可能有助于解释这一点。由于格式错误,您会得到输出。它需要在点后加一个数字,如“%.2#s”
    。无论如何,这并不重要,因为字符串格式没有替代形式。这是一个很好的答案,但在我看来,它并不完全正确。请看我的答案。如果我错了,请让我知道。
    printf("Hexadecimal:\t%x %x %X %#x\n", 5, 10, 10, 6);
    printf("Octal:\t%o %#o %#o\n", 10, 10, 4);