5

请解释输出。%.#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
4

3 回答 3

7

这是未定义的行为。#in printfformat specifier 表示替代形式,但根据标准,#仅与o, a, A, x, X, e, E, f, F, g,一起使用G,不包括s.

C11 §7.21.6.1功能fprintf6 节

#结果将转换为“替代形式”。对于o转换,当且仅在必要时,它会增加精度,以强制结果的第一个数字为零(如果值和精度都是00则打印一个)。对于x(or X) 转换,非零结果具有0x(or 0X) 前缀。对于a, A, e, E, f, F, g, 和G转换,浮点数的转换结果总是包含一个小数点字符,即使它后面没有数字。(通常,小数点字符仅在其后有数字时才会出现在这些转换的结果中。)对于gG转换,尾随零不会从结果中删除。对于其他转换,行为未定义。

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

于 2013-08-30T07:21:15.147 回答
4

%.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);
于 2013-08-30T07:34:38.040 回答
1

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

§6.21.6.1 中的 C11 标准说,该%符号后面依次是:

  1. 零个或多个标志(包括#
  2. 可选的最小字段宽度
  3. 可选精度
  4. 可选的长度修饰符
  5. 转换说明符

除了转换说明符,这些都是可选的。但它们出现的顺序始终如上。因此,如果存在 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)在这里发生的事情。

于 2013-08-30T07:31:51.493 回答