c - 标准 C 中的约束是什么?

标签 c standards language-lawyer

C 标准谈​​论约束,例如。 G。 ISO/IEC 9899:201x 定义了该术语

constraint
restriction, either syntactic or semantic, by which the exposition of language elements is to be interpreted



并在第 章一致性 中说

If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined.



在章节 环境 , 小节 诊断 据说

A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined.



因此,了解 C 中的约束是很重要的,例如对于编译器编写者判断何时需要诊断,或者对于 C 程序员何时需要诊断而不仅仅是未定义的行为。
现在,整个标准文档都有标题为 Constraints 的部分,但我找不到关于标准中术语约束到底涵盖什么内容的明确措辞。
  • 约束是否在标题为 约束 的部分中出现?
  • 在这些部分之外陈述的每个要求都不是约束吗?
  • 我错过的标准中是否有对约束的全面描述?
  • 最佳答案

    Are the constraints everything that appears in the sections titled Constraints?



    在 n1570 3.8 的意义上(对程序施加的限制,该程序需要符合要求的实现才能在违反时发出编译时诊断消息),我认为是的。

    Is every requirement that is stated outside of those sections not a constraint?



    在 3.8 的意义上,我认为是的,但出于更循环的原因:标准的结构相当正式。只要适用,似乎就有一个明确的约束部分。因此,我理解根据定义,任何不在约束部分中的内容都不是 3.8 意义上的约束。
    在 Constraints 部分之外有一些“shall”子句,它们看起来完全可以在编译时强制执行,参见。下面举几个例子。它们通常位于相邻的语义部分。我可能遗漏了在一般情况下阻止编译时检测的微妙之处(因此不能强制进行诊断),或者标准可能不完全一致。但我认为编译器可以简单地翻译一个违规的程序,正是因为这些要求不在约束部分。

    Is there a comprehensive description of constraint in the standard that I missed?



    我认为 3.8 就是你所得到的。我尝试探索下面的术语并同意该定义不令人满意。

    我更深入地研究了标准以找出答案。这是我的研究。

    术语约束

    让我们从基础开始。您引用的 3.8 中“约束”的定义令人惊讶地难以理解,至少在没有上下文的情况下(“要解释语言元素的说明的句法或语义限制”)。 “限制”和“约束”是同义词,所以改写不会增加太多; “语言元素的阐述”是什么意思??博览会是一个有多种含义的词;让我们以来自 Dictionary.com 的“主要用于传达信息的写作或演讲”为例,让我们假设他们的意思是标准。那么它基本上意味着本标准中的约束是本标准中所说的约束。哇,我没想到。

    根据 3.8 的约束

    务实地检查标准中的实际约束部分显示它们列出 强加于符合程序的编译时间限制。 这是有道理的,因为在编译时只能检查编译时约束。
    这些额外的限制是不能用 C 语法表达的。 1

    约束部分之外的约束

    约束部分之外“应”的大多数用法对符合要求的实现施加限制。 示例:“所有具有静态存储持续时间的对象都应被初始化(设置为它们的
    初始值)在程序启动之前”,符合实现的工作。

    但是,有一些“应”子句对约束部分之外的程序(而不是实现)施加了限制。我认为大多数与 3.18 中提到的“调用库函数时程序上的运行时约束 [...]”属于同一类别。它们似乎是在编译时通常无法检测到的运行时约束(因此诊断不是强制性的)。

    这里有一些例子。

    在 6.5/7 n1570 中详细介绍了备受争议的别名规则:

    An object shall have its stored value accessed only by an lvalue expression that has one of the following types:

    • a type compatible with the effective type of the object
    • a qualified version of a type compatible with the effective type of the object, [...]


    在 6.5.16.1,“简单赋值”中:

    If the value being stored in an object is read from another object that overlaps in any way the storage of the first object, then the overlap shall be exact[..]."



    其他示例涉及指针算术 (6.5.6/8)。

    可以在约束部分中的 SHALL 子句

    但是还有其他应该在编译时检测到违规的shall子句;如果它们出现在相应的约束部分,我不会眨眼。
  • 6.6/6, "在整数常量中转换运算符
    表达式应仅将算术类型转换为整数类型”(在“语义”下);如果无法检测常量和强制转换的类型,您在编译时可以检测到什么?
  • 6.7/7,“如果一个对象的标识符是在没有链接的情况下声明的,则该对象的类型应在其声明符的末尾完成”(在“语义”下)。对我来说,这似乎是一项基本的编译器任务,用于检测代码中某个点的类型是否完整。但当然,我从来没有写过 C 编译器。

  • 还有几个例子。但正如我所说,我认为不需要实现来诊断违规行为。设法绕过编译器的违规程序只会暴露未定义的行为。

    1 例如,我知道语法不处理类型——它只有通用的“表达式”。因此,每个运算符都有一个约束部分,详细说明其参数的允许类型。移位运算符示例:“每个操作数都应具有整数类型。”试图移动浮点数位的程序违反了此约束,实现必须发出诊断信息。

    关于c - 标准 C 中的约束是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33409241/

    相关文章:

    C - 数组超出范围

    c++ - 当重载函数作为参数涉及时,模板参数推导如何工作?

    .net - .Net MailMessage 自动折叠 header 字段是否长于 RFC2822 最大长度?

    c++ - (int32_t) 255 << 24 是 gcc (C++11) 中的未定义行为吗?

    c++ - 为什么链接器不会在下面的代码中发出错误?

    c++ - 内存耗尽会导致段错误吗?

    c++ - 嵌入式文件作为 char 数组的编译器问题

    C - 动态调整二维字符数组的大小

    c++ - 在 C++ 中为零大小的分配返回唯一地址的基本原理是什么?

    standards - MIME 类型的约定、标准或限制?