C99标准中的 printf 函数描述(英文翻译)

C99标准中的 printf 函数描述(英文翻译)

前言

  由于本人翻译水平有限,以下翻译可能存在部分不容易理解的或者不正确的内容,如有对以下内容存有疑问或者想指出翻译错误之处,请在下方留言。对于翻译中可能存在的不太通顺的句子,请参考英文原文辅助理解,详见本人整理的相关英文副本 C99标准 printf 函数描述(英文原文)

格式化输入/输出函数

  格式化输入/输出函数应该表现得像每个说明符相关联的动作后面都有一个序列点一样[1]。关于序列点的介绍请参考本人的另一篇博文。

  [1] fprintf 函数为 %n 说明符执行写入内存的操作。

printf 函数

概要

  #include <stdio.h>

int printf(const char * restrict format, ...);

描述

  printf 函数等价于在 printf 的参数之前插入了 stdout 参数的 fprintf 函数。

返回

  printf 函数返回传输的字符数,如果出现输出或编码错误,则返回一个负数。
  
  
  

fprintf 函数

概要

  #include <stdio.h>

int fprintf(FILE * restrict stream, const char * restrict format, ...);

描述

  fprintf 函数将输出写入 stream 所指向的流,由 format 所指向的字符串控制,该字符串指定如何将后续参数转换为输出。如果格式没有足够的参数,则行为是未定义的。如果格式耗尽而参数仍然存在,多余的参数会被计算(一如既往),但是会被忽略。当遇到格式字符串的末尾(空字符)时,fprintf 函数返回。

  格式应该是一个多字节字符(强调多字节字符是为了区别于宽字符)序列,开始和结束在其初始转换状态。该格式由零个或多个指示符:普通多字节字符(非%),它们被不变地复制到输出流;和转换说明组成,每个转换说明都会导致获取零个或多个后续参数,如果适用的话,根据相应的转换说明符对它们进行转换,然后将结果写入输出流。

  每个转换说明都是由字符 % 引入的。在 % 之后,依次出现以下内容:

  • 零个或多个修饰转换说明含义的标志(顺序不限)。
  • 可选的最小字段宽度。如果转换后的值的字符数少于字段宽度,则在字段宽度的左侧(或者右侧,如果给出了左对齐标志,详见下文)用空格(默认)填充。字段宽度采用星号 *(详见下文)或十进制整数的形式[3]
  • 一个可选的精度,给出了 d,i,o,u,x 和 X 转换的最少输出的数字位数(不足则在前面补0),a,A,e,E,f 和 F 转换的小数点字符后出现的小数位数。g 和 G 转换的最大有效数字位数,或者s转换要写入的最大字节数。精度采用句点(.)的形式,后跟星号 *(详见下文)或可选的十进制整数;如果只指定句点,则精度为零。如果精度与任何其他转换说明符一起出现,则该行为未定义。
  • 一个可选的长度修饰符,指定实参的大小。
  • 转换说明符,指定要应用的转换类型。

  [3] 注意,0 被作为一个标志,而不是字段宽度的开始。

  如上所述,字段宽度精度,或两者都可以用星号表示。在这种情况下,一个 int 实参提供字段的宽度或精度。指定字段宽度或精度,或两者的实参,必须(按顺序)出现在要转换的实参(如果有的话)之前。负的字段宽度实参被当作一个 - 标志,后面跟着一个正的字段宽度。如果忽略了精度,则接受一个负精度实参。

  标志字符及其含义如下:

标志 含义
   -    转换的结果在字段内左对齐。(如果没有指定这个标志,它就是右对齐的。)
+ 有符号转换的结果总是以加号或减号开始。(如果未指定此标志,则只有在转换负值时才以符号开始。)
空格 如果有符号转换的第一个字符不是符号,或者有符号转换不产生任何字符,则在结果前加一个空格。如果空格和 + 标志同时出现,空格标志将被忽略。
# 结果被转换为“另一种形式”。对于 o 转换,当且仅当必要时,它会提高精度,强制结果的第一个数字为零(如果值和精度都为0,则打印单个0)。对于 x(或 X)转换,一个非零结果有 0x(或 0X)前缀。对于a,A,e,E,f,F,g 和 G 转换,浮点数转换的结果总是包含一个小数点字符,即使它后面没有数字。(通常,只有在后面跟着一位数字时,小数点字符才会出现在这些转换的结果中。)对于g和g转换,结果末尾的0不会被删除。对于其他转换,行为是未定义的。
0 对于 d,i,o,u,x,X,a,A,e,E,f,F,g,G 的转换,前导零(跟随在符号或基底表示后面)用于填充字段宽度,而不是执行空格填充,除非转换无穷大或非数值。

  长度修饰符及其含义如下:

修饰符 含义
    hh     指定后面的 d,i,o,u,x 或 X 转换说明符应用于 signed char 或 unsigned char 实参(实参将根据整型提升而提升,但其值在打印之前应当转换为 signed char 或 unsigned char);或者后面的 n 转换说明符应用于指向 signed char 实参的指针。
h 指定后面的 d,i,o,u,x 或 X 转换说明符应用于 short int 或 unsigned short int 实参(实参将根据整型提升而提升,但其值在打印前应当转换为 short int 或 unsigned short int);或者后面的 n 转换说明符应用于指向 short int 实参的指针。
l 指定后面的 d,i,o,u,x 或 X 转换说明符应用于 long int 或 unsigned long int 实参;或者后面的 n 转换说明符应用于指向 long int 实参的指针;或者后面的 c 转换说明符应用于 wint_t 实参;或者后面的 s 转换说明符应用于指向 wchar_t 实参的指针;对后面的 a,A,e,E,f,F,g 或 G 转换说明符没有影响。
ll 指定后面的 d,i,o,u,x 或 X 转换说明符应用于 long long int 或 unsigned long long int 实参;或者后面的 n 转换说明符应用于指向 long long int 实参的指针。
j 指定后面的 d,i,o,u,x 或 X 转换说明符应用于 intmax_t 或 uintmax_t 实参;或者后面的 n 转换说明符应用于指向 intmax_t 实参的指针。
z 指定后面的 d,i,o,u,x 或 X 转换说明符应用于 size_t 或相应的有符号整数类型实参;或者后面的 n 转换说明符应用于指向与 size_t 相对应的有符号整型实参的指针。
t 指定后面的 d,i,o,u,x 或 X 转换说明符应用于 ptrdiff_t 或相应的无符号整型实参;或者后面的 n 转换说明符应用于指向 ptrdiff_t 实参的指针。
L 指定后面的 a,A,e,E,f,F,g 或 G 转换说明符应用于 long double 参数。

  如果长度修饰符与上面指定的转换说明符以外的任何转换说明符一起出现,则该行为是未定义的。

  转换说明符及其含义:

说明符 含义
d,i int 实参被转换成带符号的十进制形式,格式为 [−]dddd。精度指定最少要输出的数字位数;如果要转换的值可以用更少的数字表示,则用前导零扩充。默认精度为1。使用精度为零对零值进行转换的结果是没有字符。
o,u,x,X unsigned int 实参被转换为无符号八进制(o),无符号十进制(u),或无符号十六进制表示法(x或X),格式为 dddd。字母 abcdef 用于 x 转换,字母 ABCDEF 用于 X 转换。精度指定最少要输出的数字位数;如果要转换的值可以用更少的数字表示,则用前导零扩充。默认精度为1。使用精度为零对零值进行转换的结果是没有字符。
f,F 表示浮点数的 double 实参被转换成 [−]ddd.ddd 样式的十进制表示法,小数位数由精度指定。如果缺省精度,则默认值为6 。如果精度为零且未指定 # 标志,则不会出现小数点字符。如果出现小数点字符,则在其前面至少出现一位数字。该值四舍五入到合适的数位。

表示无穷大的 double 实参被转换为 [-]inf 或者 [-]infinity 中的一种样式,这是实现定义的。表示 NaN 的 double 实参被转换为 [-]nan 或 [-]nan(n-char-sequence) 中的一种样式,具体哪种样式及任何 n-char-sequence 的含义都是实现定义的。对于 F 转换说明符,分别由 INF,INFINITY 或 NAN 替代 inf,infinity 或 nan。
e,E 表示浮点数的 double 实参被转换成 [−]d.ddde±dd 样式,在小数点字符之前有一位数字(如果实参是非零,则为非零),小数点后的位数取决于精度;如果缺省精度,则默认值为6 。如果精度为零且未指定 # 标志,则不会出现小数点字符。该值四舍五入到合适的数位。E 转换说明符使用带 E 的数字而不是带 e 的数字引入指数。指数总是包含至少两位数字,并且只包含表示指数所需的更多位数字。如果值为零,则指数为零。

表示无穷大或 NaN 的 double 实参将按照 f 或 F 转换说明符的样式进行转换。
g,G 表示浮点数的 double 实参以样式 f 或 e 进行转换(对于 G 转换说明符,则采用样式 F 或 E),精度指定有效数字的位数。如果精度为零,则取为1。所使用的样式取决于转换的值;样式 e(或 E)仅在转换后的指数小于−4或者大于或等于精度时使用。除非指定了 # 标志,否则结果的小数部分会移除末尾的零;小数点字符只在后面跟着一位数字时出现。

表示无穷大或 NaN 的 double 实参将按照 f 或 F 转换说明符的样式进行转换。
a,A 表示浮点数的 double 实参被转换成 [−]0xh.hhhhp±d ,在小数点字符之前有个十六进制的数字(如果实参是规范化的浮点数,则该数字为非零,否则是未指定的),小数点字符后面的十六进制数的位数取决于精度。如果缺省精度且 FLT_RADIX 为2的幂,则精度足以精确表示该值。如果缺省精度且 FLT_RADIX 不是2的幂,那么精度足以区分 double 类型的值,只是末尾的0可以忽略;如果精度为零且未指定 # 标志,则不会出现小数点字符。字母 abcdef 用于 a 转换,字母 ABCDEF 用于 A 转换。A 转换说明符使用 X 和 P 而不是 x 和 p。指数总是至少包含一位数字,并且只包含表示2的十进制指数所需的更多位数字。

表示无穷大或 NaN 的 double 实参将按照 f 或 F 转换说明符的样式进行转换。
c 如果没有 l 长度修饰符,则将 int 实参转换为 unsigned char,并写入结果字符。

如果存在 l 长度修饰符,则对 wint_t 实参进行转换,就像使用 ls 转换说明进行转换一样且没有精度,而实参指向含两个元素的 wchar_t 数组的初始元素。第一个元素包含 lc 转换说明的 wint_t 实参,第二个元素是空宽字符。
s 如果没有 l 长度修饰符,实参应当是一个指向字符类型数组初始元素的指针。数组中的字符被写入直到(但不包括)末尾的空字符。如果指定了精度,则写入的字节数不会超过这个数。如果精度没有指定或者大于数组的大小,数组中应该包含一个空字符。

如果存在 l 长度修饰符,则实参必须是指向 wchar_t 类型数组初始元素的指针。数组中的宽字符被转换为多字节字符(每个都像是调用 wcrtomb 函数一样,在转换第一个宽字符之前,由 mbstate_t 对象描述的转换状态初始化为零)直到并包括结束的空宽字符。生成的多字节字符被写入直到(但不包括)末尾的空字符(字节)。如果没有指定精度,数组应该包含一个空宽字符。如果指定一个精度,不会超过那么多字节被写入(包括转换序列,如果有的话),无论何时数组中应当包含一个空宽字符,为了使多字节字符序列长度与精度相等,该函数需要访问数组结束后的一个宽字符。在任何情况下都不会写入部分多字节字符。
p 实参应当是一个指向 void 的指针。指针的值被转换成一个打印字符序列,以一种实现定义的方式。
n 实参应当是一个指向有符号整数的指针,这个实参被写入通过调用 fprintf 写入输出流到目前为止的字符数。不转换实参,只消耗一个实参。如果转换说明包含任何标志、字段宽度或精度,则行为未定义
% 写入一个%字符。不转换参数。完整的转换说明为%%。
      

  如果转换说明无效,则行为未定义。如果任何实参不是对应转换说明的正确类型,则行为未定义。

  在任何情况下都不会因不存在或字段宽度小而导致字段截断;如果转换的结果比字段宽度宽,则将扩展字段以包含转换结果。

  对于 a 和 A 转换,如果 FLT_RADIX 是2的幂,则该值将正确舍入为具有给定精度的十六进制浮点数。

推荐作法

  如果 FLT_RADIX 不是2的幂,则结果应该是给定精度的两个十六进制浮点样式的相邻数字中的一个,并额外规定误差应该有当前舍入方向的正确符号。

  对于 e,E,f,F,g 和 G 转换,如果有效小数位数最多为 DECIMAL_DIG,那么结果应该是正确的四舍五入。如果有效小数位数大于 DECIMAL_DIG,但源值可以用 DECIMAL_DIG 位精确表示,那么结果应该是一个尾随0的精确表示。否则,源值以两个相邻的小数字符串 L<U 为界,两者都有 DECIMAL_DIG 有效位;作为结果的小数字符串 D 的值应满足 L≤D≤U 。附加的规定是,误差的当前舍入方向应该有正确的符号。

返回

  fprintf 函数返回传输的字符数,如果出现输出或编码错误,则返回一个负数。

环境限制

  任何一次转换可以产生的字符数至少为4095。
  
  
  

猜你喜欢

转载自blog.csdn.net/weixin_44567318/article/details/115199102