1

后续问题:如果违反了“应/不应”要求,那么该要求位于哪个部分(例如语义、约束)是否重要?.

ISO/IEC 9899:202x (E) 工作草案——2020 年 12 月 11 日 N2596,5.1.1.3 诊断,1:

如果预处理翻译单元或翻译单元包含违反任何语法规则或约束的行为,则符合的实现应产生至少一个诊断消息(以实现定义的方式标识),即使该行为也明确指定为未定义或实现-定义。在其他情况下不需要生成诊断消息。

结果:语义违规不需要诊断。

问题:“语义违规不需要诊断”的(可能)理由是什么?

4

4 回答 4

4

A possible rationale is given by Rice's theorem : non-trivial semantic properties of programs are undecidable

For example, division by zero is a semantics violation; and you cannot decide, by static analysis alone of the C source code, that it won't happen...

A standard cannot require total detection of such undefined behavior, even if of course some tools (e.g. Frama-C) are sometimes capable of detecting them.

See also the halting problem. You should not expect a C compiler to solve it!

于 2021-10-21T11:15:27.573 回答
2

发生这种情况是因为C 语言的语法是上下文敏感的,并且对于所有使用上下文无关或更复杂的语法定义的语言来说,Chomsky 层次结构必须在语言的语义和它的能力之间进行权衡。

C 设计者选择为语言提供很大的权力,这就是为什么不可判定性问题在 C 中无处不在。

有像 Coq 这样的语言试图消除不可判定的情况,它们限制了递归函数的语义(它们只允许 sigma(primitive) 递归)。

于 2021-10-21T11:50:15.740 回答
2

实施是否在任何特定情况下提供任何有用的诊断的问题是标准管辖范围之外的实施质量问题。如果一个实现无条件地输出“警告:这个程序没有输出任何有用的诊断”甚至“警告:水是湿的”,那么即使实现没有,这样的输出也将完全满足标准关于诊断的所有要求输出任何其他诊断。

此外,该标准的作者将许多行为描述为“未定义的行为”,他们期望这些行为会被许多(如果不是大多数)实现以有意义和有用的方式处理。根据已发布的基本原理文档,未定义的行为除其他外“识别符合语言扩展的区域”,因为允许实现指定它们在标准未定义的情况下的行为方式。

让实现对不可移植的构造发出警告,但它们会以有用的方式处理这些构造会很烦人。

在标准之前,一些实现将有用地接受以下结构:

struct foo {
  int *p;
  char pad [4-sizeof (int*)];
  int q,r;
};

对于不超过四个字节的所有大小的指针(当时还没有 8 字节指针),而不是在指针正好是四个字节时大喊大叫,但是委员会中的一些人反对接受零声明的想法-大小的数组。因此,达成了一种妥协,编译器会对这些事情大喊大叫,程序员会忽略无用的警告,而有用的结构将在支持它们的实现上仍然可用。

虽然有一种模糊的尝试来区分应该产生程序员可以忽略的警告的构造,与可能使用太多以至于警告会令人讨厌的构造,但发布有用的诊断是标准管辖范围之外的实施质量问题意味着没有必要过多担心这种区别。

于 2021-11-24T23:21:22.690 回答
2

C99 基本原理 v5.10 给出了这样的解释:

5.1.1.3 诊断

通过对包含语法错误或约束违规的任何程序强制要求某种形式的诊断消息,该标准执行两项重要服务。首先,它为错误程序的概念提供了依据,因为符合要求的实现必须将此类程序与有效程序区分开来。其次,它严格限制了符合实现的扩展的性质。

该标准没有说明诊断消息的性质,它可能只是“语法错误”,没有提示错误发生的位置。(当然,实现必须描述什么翻译器输出构成诊断消息,以便用户能够识别它。)C89 委员会最终决定,任何超出此级别的诊断活动都是实现质量问题,并且市场力量将鼓励更有用的诊断。尽管如此,C89 委员会认为至少必须诊断出一些重要的错误类别,并且指定的类别应该被所有翻译人员识别。

于 2021-10-21T11:28:05.113 回答