4

根据C11第 7.21.6.1 章 P9

如果转换规范无效,则行为未定义。282)如果任何参数不是相应转换规范的正确类型,则行为未定义。

直到那时,我的理解是,因为

  char str [] = "Sourav";
  • 语句likeprintf("%S", str);属于第一句,不存在CS as %S(UPPERCASE)
  • 语句 likeprintf("%d", str);属于第二句(CS 和参数类型不匹配,但无论如何都不%d是“无效”的 CS)

直到最近的评论线程另有通知

我的理解错了吗?第二个语句可以归类为“无效”(PS-不是“错误”)转换说明符吗?


更新:答案和评论线程已被删除,这是 <10K 用户的快照

4

3 回答 3

9

转换规范的“有效性”由您引用的上述标准段落确定:

7.21.6.1 - p4 到 p8

每个转换规范都由字符 % 引入。在 % 之后,依次出现以下内容: ...

标志字符及其含义是: ...

转换说明符及其含义是: ...

这意味着由上述列表中的元素组成的任何转换规范都是有效的,所有其他的都不在标准的眼中。这就是为什么您的代码中的段落提到了导致 UB 的两个原因。一种是规范不符合语法,另一种是规范和类型不匹配。

您链接到的评论似乎通俗地使用“无效”。即转换规范的两种用法都是“无效的”,因为它们会导致 UB。但从语言律师的角度来看,只有第一个是“无效的”。

于 2017-08-09T10:54:28.817 回答
1

脚注 282 指向未来图书馆方向 C11 7.31.11p1

fprintf 和 fscanf 中的转换说明符和长度修饰符可以添加小写字母。其他字符可以在扩展中使用。

所以它也暗示无效的转换说明符意味着那些不在列表中的转换说明,其中小写字母可能会被未来的 C 版本使用;并且扩展名可以随意使用其他字母。


C11 附录 J.2,虽然是非规范性的。包含以下内容:

  • 在格式化输入/输出函数之一或strftimeorwcsftime函数(7.21.6.1、7.21.6.2、7.27.3.5、7.29.2.1、7.29.2.2、7.29.5.1)的格式中发现无效的转换规范。

即,无效的转换规范 to*printf在这里与无效的转换规范配对strftime- 它不接受可变参数,并且无效不会由于转换规范和相应参数之间的不匹配而引起;

这可以与

  • 调用格式化输入/输出函数之一时格式的参数不足,或者参数没有适当的类型(7.21.6.1、7.21.6.2、7.29.2.1、7.29.2.2)。

它讨论了参数和转换说明符之间的不匹配,没有提到无效这个词。

于 2017-08-09T12:23:45.647 回答
1

To support my understanding (and probably to reasonify the understanding in first place), let me add my two cents.

一会儿,让我们看看脚注 282,如引用中所述。它说,

见“未来图书馆方向”(7.31.11)。

并在 §7.31.11

小写字母可以添加到 和 中的转换说明符和长度 fprintf修饰符fscanf。其他字符可以在扩展中使用。

其中没有提到 CS 与其论点(如果有的话)之间的关系。因此,CS 的“有效性”不依赖于提供的参数。

现在,也就是说,还有几个指针

  • 第 1 点 :: 请注意引用中提到的短语“转换规范”,而不是 转换说明符。根据第 7.21.6.1/P4 章,

    每个转换规范都由字符引入%。之后%,依次出现以下内容:

    • 零个或多个标志 [...]

    • 可选的最小字段宽度 [...]

    • 可选精度 [...]

    • 可选的长度修饰符 [...]

    • 转换说明符字符 [...]

    我们有明确的清单,列出所有提到的元素

    • P5,场宽和精度
    • P6,旗帜
    • P7,长度修饰符
    • P8,转换说明符

    因此,与提供的参数没有(或应该)没有关系来识别转换规范的“有效性”。

    为了补充这种理解,借用Ajay Brahmakshatriya 的评论

    “我认为这里的操作词是“对应”。第一句话说如果字符串中存在一个无效的说明符。如果没有,那么每个说明符与其对应的参数匹配。然后第二个语句说关于类型匹配.....我认为第二个例子不属于第一类,因为没有使用“对应””

  • 第 2 点 ::另一方面,规范对于 CS 和提供的相应参数类型之间的“不匹配”非常明确和清楚。所以,这是完全不同的情况。

现在,例如,如果两种情况结合在一起,很难判断是哪种情况导致了 UB,但肯定是 UB,原因不止一个。

例子:

   printf("%D", str);

跟随问题。

于 2017-08-09T11:27:21.727 回答