标准C中的约束是什么?

时间:2015-10-29 08:29:11

标签: c standards language-lawyer

C标准谈论约束,e。 G。 ISO / IEC 9899:201x 定义术语

  

约束
  限制,无论是句法还是语义,通过它来限制   语言元素的阐述将被解释

并在一致性

章中说
  

如果''''或'''''''要求出现在a。之外   违反了约束或运行时约束,行为是   未定义。

环境一章中,分节诊断,据说

  

符合要求的实施应至少产生一种诊断   消息(以实现定义的方式标识)如果a   预处理翻译单元或翻译单元包含一个   违反任何语法规则或约束,即使行为是   也明确指定为未定义或实现定义。

因此,重要的是要知道C中的约束是什么,例如编译器编写者判断何时需要诊断,或者C编程人员在诊断时而不仅仅是未定义的行为时。 现在,标准文档中有一些标题为约束的部分,但我无法找到关于约束这个术语在标准中涵盖的确切措辞。

  • 约束是否出现在标题为约束
  • 的部分中
  • 在这些部分之外陈述的每项要求都不是约束条件吗?
  • 我错过了标准中约束的全面描述吗?

7 个答案:

答案 0 :(得分:9)

  

约束是否出现在标题为约束的部分?

在n1570 3.8的意义上(对程序施加的限制,要求在违反时要求符合规范的实施发出编译时诊断消息),我想是的。

  

在这些部分之外陈述的每项要求都不是约束条件吗?

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

  

我错过了标准中约束的全面描述吗?

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

我更深入地研究了这个标准。这是我的研究。

术语约束

让我们从基础开始。 "约束"的定义在3.8中你引用的是令人惊讶的难以理解,至少没有上下文("限制,无论是语法还是语义,通过它来解释语言元素的阐述")。 "约束"和"约束"是同义词,因此重写不会增加太多;什么是"语言元素的阐述" ??博览会是一个有多种含义的词;让"写作或演讲主要是为了从Dictionary.com传达信息" ,让我们假设它们是标准的。那么它基本上意味着该标准中的约束是本标准中所述内容的约束。哇,我不会猜到的。

根据3.8

约束

务实地只是检查标准中的实际约束部分,表明它们列出了对强制执行程序编译时限制。这是有道理的,因为只能在编译时检查编译时约束。 这些附加限制是那些无法用C语法表达的限制。 1

约束部分

之外的约束

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

有一些"将"但是,在 Constraints 部分之外对程序(不是实现)施加限制。我认为,当调用库函数时,大多数属于与程序运行时约束相同的类别"在3.18中提到。它们似乎是运行时限制,通常在编译时无法检测到(因此诊断不能强制执行)。

以下是一些例子。

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

  

对象只能访问其存储值   通过具有其中一个的左值表达式   以下类型:

     
      
  • 与对象的有效类型兼容的类型
  •   
  • 兼容类型的合格版本   与对象的有效类型,   [...]
  •   

在6.5.16.1中,"简单分配":

  

如果从另一个以任何方式重叠的对象读取存储在对象中的值   存储第一个对象,然后重叠应该是精确的[...]。"

其他例子涉及指针运算(6.5.6 / 8)。

可以在约束部分中的子句

但是还有其他条款,在编译时可以检测到违规;如果它们出现在相应的 Constraints 部分中,我就不会眨眼。

  • 6.6 / 6,"以整数常量转换运算符 表达式只能将算术类型转换为整数类型" (在" Semantics"下);如果你不能检测常量和强制类型的类型,你可以在编译时检测到什么?
  • 6.7 / 7,"如果声明对象的标识符没有链接,则对象的类型应在其声明者的结尾处完成" (在&下) #34;语义&#34)。对我来说,似乎是一个基本的编译器任务,用于检测代码中某个类型是否完整。但当然,我从未编写过C编译器。

还有一些例子。但正如我所说,我认为诊断违规行为不需要实施。设法偷偷通过编译器的违规程序只会暴露未定义的行为。

<小时/> 1 例如,我理解语法不处理类型 - 它只有通用&#34;表达式&#34;。因此,每个运算符都有一个 Constraints 部分,详细说明了其参数的允许类型。移位运算符的示例:&#34;每个操作数都应具有整数类型。&#34; 试图移位浮点数的程序违反了此约束,并且实现必须发出诊断。

答案 1 :(得分:7)

C委员会在回复Defect Report # 033时解决了这个问题。该缺陷报告中的问题是:

  

是否需要符合规定的实施方案来诊断所有违反“&#39;&#39;&#39;&#39;&#39;&#39;&#39;并且&#39;&#39;&#39;&#39;&#39;&#39;&#39;标准中的语句,即使这些语句出现在标记为约束的部分之外?

该缺陷报告的作者提出了几种可能的解释标准语言的替代方法。他列出的第二种选择(部分):

  

语法规则是标准的语法部分中列出的项目。 约束是标准约束部分中列出的项目。

委员会的部分回应是:

  

建议的解释#2是正确的解释。

我认为这完全涵盖了您的问题,但只是更直接地陈述您的问题的答案:

  
      
  • 约束是否出现在标题为约束的部分?
  •   
  • 在这些部分之外陈述的每项要求都不是约束条件吗?
  •   

A&#34;约束&#34;是明确标记为&#34;约束&#34;的部分中规定的要求。在这样的部分之外陈述的任何要求都不是约束。

  
      
  • 我错过了标准中对约束的全面描述吗?
  •   

至少据我所知,标准本身并没有包含更具体的声明,关于什么是或不是约束,但链接的缺陷报告确实如此。< / p>

答案 2 :(得分:2)

  

约束是否出现在标题为约束的部分?

它们似乎主要是(有些情况不是,fx:它表示&#34;增量相当于在一个约束部分中添加1&#34;)

  

在这些部分之外陈述的每项要求都不是约束条件吗?

我还没有看到&#34;约束&#34;在这些部分之外。

  

我错过了标准中对约束的全面描述吗?

可能不是,如果有一个权威的,那么它将在标准中并且可能是&#34;约束&#34;部分(并明确提到这些都是&#34;约束&#34;)。

我的解释是第3章应该被解释,以便定义的术语的每一次使用都具有该部分中定义的含义。特别是在任何地方,术语&#34;约束&#34;使用它应该根据你的第一个引用来理解。

你的第二句话也不例外。它在术语&#34;约束&#34;的定义中提到了它。没有要求约束明确地称为约束。这意味着你必须确定它是否是一个&#34;约束&#34;通过检查它是否是这样的限制。

然而似乎有很多例子&#34; will&#34;并且&#34;不得&#34;这可以被视为这样的限制而没有明确地被称为这样的限制。这将留下所有的事件&#34;将&#34;并且&#34;不得&#34;强制执行或禁止实现的某些行为 - 如果这些行为未得到满足,那么行为可能是不确定的(因为您使用的实施不符合标准)。

看起来所有符合&#34;约束&#34;的定义。似乎发生在&#34;约束下#34;部分,以及&#34;约束中的所有内容&#34;部分似乎是&#34;约束&#34;。

答案 3 :(得分:1)

  

约束是否出现在标题为约束的部分中?

是。标准中提到的每个语法和语义限制都是约束。

例如,对常量表达式(C11-6.6 / 3)的约束:

  

常量表达式不应包含赋值,递增,递减,函数调用或逗号运算符,除非它们包含在未评估的子表达式中。 115)

因此,常量表达式

3 = 5;
10++;

显示约束违规。

请注意,在这种情况下,必须要求以及约束都会被违反。

  

在这些部分之外陈述的每项要求都不是约束条件吗?

对于标准符合C,是的。 要求整数常量表达式(C11-6.6 / 6):

  

整数常量表达式 117) 必须具有整数类型[...]

例如,非可变长度数组的大小需要整数常量表达式。因此,

int arr[5+1.5];

违反了 要求。表达式5+1.5的类型不是整数类型。 要求不受约束。

应该注意, 要求也可能是一个约束。

答案 4 :(得分:1)

在我的需求工程工作中,“约束”和“要求”这两个词的范围不同。同样,对于标准来说,明确地定义它们也很重要。我在标准中搜索了“约束”这个词,似乎我可以得出以下结论:

约束是对标准部分描述的行为的输入(前置条件)或输出(后置条件)的限制。对于输入,它意味着输入必须遵守约束(例如argc应为正)。对于输出,它意味着它必须满足标准的任何后续单位的约束,以具有明确定义的输入(其前置条件)。

要求是标准部分行为规范的一部分。 “应该”是对所需要的积极描述; “不应该”通常是限制,但不是约束 - 它可以参与但是在满足其输出的限制时。

约束和要求可以看作是“外部接口”(约束)和“系统行为/处理”(要求)。

一般表示要求(没有“须”的短语因此不是要求)。然后,在约束中使用的“应该”用于定义输入或输出(例如argc应为正)或指定有关验证约束的行为(例如“......应给出诊断消息”)。 / p>

严格地说,用于指定验证输入约束的行为的“shall”不应列在约束部分中(不应在接口规范中列出),而应列在处理部分(行为部分)中。

请注意,输出约束无法验证,因为输出应符合规范;只有下一个uit可以检查这些约束是否在输入约束中。

这可能是个人观点,但它似乎符合标准中这些词语的用法。

答案 5 :(得分:0)

  

约束

     

限制,无论是句法还是语义,通过它来限制   语言元素的阐述将被解释

这意味着c standart以任何方式设置的程序逻辑或语法的每个显式限制都是约束。这包括语法约束(例如,块必须以;终止)和语义约束(例如,在初始化之前不应使用变量),基本上是语法(符号)或语义上的所有内容(使用正确的表示法)不允许或定义为不允许(未定义的行为)。

  

在这些部分之外陈述的每项要求都不是   约束

我确实认为C语言编程的所有明确要求都属于句法或语义约束。

  

标准中是否有对约束的全面描述   我错过了吗?

据我所知。

答案 6 :(得分:0)

标准中约束的目的是指定符合要求的实现需要发出诊断的条件,或者允许实现可以在没有约束的情况下以与没有约束的情况下所需的方式相反的方式处理程序可能比其他指定的行为有用。尽管不允许严格符合 C 程序违反约束(任何违反约束的程序都是严格符合 C 程序),但此类限制不适用于旨在符合但不符合严格符合的程序。

C 标准是作为多个重叠派系之间的妥协而编写的,包括

  1. 那些认为它应该阻止程序员编写不能在所有平台上互换运行的代码的人
  2. 那些认为它应该允许以已知平台为目标的程序员利用他们需要支持的所有平台共有的功能的人,即使这些功能在所有平台上都不受支持
  3. 那些认为应该允许编译器诊断结构和动作的人,这些结构和动作更常是偶然执行的,而不是故意执行的
  4. 那些认为它应该允许程序员执行地址计算之类的事情的人,这些事情看起来是错误的,但如果按照指定的方式精确执行,则会产生程序员期望的对象的地址。

为了在这些群体中达成共识,标准对在严格符合 C 程序中可以做什么进行了限制,但也将符合 C 程序的定义写得足够广泛,以至于几乎没有有用的程序会被贴上不符合的标签无论他们依赖的扩展多么模糊。如果源代码构造违反了可诊断的约束,但实现的客户无论如何都会发现它很有用,那么实现可以输出其客户可以忽略的诊断(甚至是无条件的:“警告:此实现不会打扰输出诊断它的作者认为很愚蠢,除了这个“就足够了),每个人都可以继续生活。

相关问题