实现定义的行为是否需要在C ++中的运行之间保持一致?

时间:2010-07-21 05:28:29

标签: c++ compiler-construction implementation

是否允许符合标准的C ++实现实现某些行为,这些行为据说是在标准中实现定义的,因为在具有相同输入数据的相同编译一次程序的不同运行之间它是不同的?

例如,一个实现是否允许说“行为是在周末这样做,否则”并根据这样的声明实现行为?

6 个答案:

答案 0 :(得分:6)

当然,如果实现文档确切的行为随着不同的运行而变化,那很好。请注意,实现定义的行为是抽象机器参数的一部分:

  

本国际标准中的语义描述定义了参数化的非确定性摘要   机。

     

抽象机的某些方面和操作在本国际标准中描述为实现定义的(例如,sizeof(int))。这些构成了抽象机器的参数。每个实施应包括描述其在这些方面的特征和行为的文件。这样的文档应该定义与该实现相对应的抽象机器的实例(在下面称为“相应的实例”)。

这不允许在单次运行的编译器中更改行为。但是在编译器的不同运行之间,编译器可以使用不同的对应抽象机器,根据实现定义的不同,抽象机器根据不同的实现定义值而不同。命令行参数如-Wall(更改实现定义的诊断消息集)是最常见的示例。除文档要求外,这与未指定的行为有所不同。未指定的行为限制性要小得多:

  

抽象机器的某些其他方面和操作在本国际标准中被描述为未指定的(例如,对函数的参数的评估顺序)。在可能的情况下,本国际标准定义了一组允许的行为。这些定义了抽象机器的非确定性方面。因此,抽象机器的实例可以为给定程序和给定输入提供多个可能的执行序列。

答案 1 :(得分:3)

我能想到的一个例子是程序是否对数字使用大端或小端表示。我相信这肯定会被视为实现定义的行为。

在某些芯片上,例如某些ARM芯片,可以在运行时切换模式,因此您可能需要一个编译器,该编译器可以生成一个以任一模式运行的程序,这意味着您具有实现定义的行为,这些行为可能会有所不同。每次运行取决于外部设置。

同样地,我猜你可以编写一个编译器,它可以生成同一程序编译的32位64位 - 并且它可以在运行时确定它执行的模式。同样,文档必须说int是32位或64位,具体取决于你如何运行它。

说实话,我看不到有人在做这些事情,但他们都听起来模糊地说明了你要求的例子,我不明白为什么他们在标准下不合法,只要文档正确记录了系统相关行为的性质。

答案 2 :(得分:1)

实施定义的行为意味着

  

Unspeci fi ed行为,其中每个实施文件如何做出选择

编译器编写者必须强制来记录特定实现的特定编程结构的行为。

  

.....以这种方式,相同的一次编译程序的不同运行与相同的输入数据不同?

Nopes!

  

例如,一个实现是否允许说“行为是在周末这样做,否则”并根据这样的声明实现行为?

我不确定,但我认为答案是

答案 3 :(得分:1)

IIRC,system()必须存在,但给定实现定义的行为。像system(“ls | grep foo”)这样的东西自然会有不同的效果,这取决于你的系统是否可以执行一个叫做ls的东西,这可能会在不同的运行之间变化。而且,即使是在一台相当普通的UNIX机器上,ls和grep也可以完成您所期望的并且不会被取出,结果仍然取决于名称中是否存在带有foo的文件,这肯定会被允许改变时间,以及执行程序的位置等。它只取决于您绘制“相同输入数据”行的位置。如果机器处于完全相同的状态,那么您可以期待相同的行为,但是没有两次运行将涉及真正处于迂腐相同状态的机器。 (即使在完全相同的机器中CPU的温度也可能导致一些限制行为,这会改变一些竞争条件的胜利者,这会明显导致程序的不同行为。)

答案 4 :(得分:1)

保证是编译器记录的内容。编译时不同的编译器标志或计算机的不同状态可能会影响编译器/优化器处理程序的方式,并可能对结果产生影响。编译器标志具有最大的影响(相同的编译器可用于在64位环境中生成32位和64位程序,在两次运行中,对齐要求可能不同)。

您可以预期,在大多数情况下,实现者将为实现的行为及其为给定的一组编译器/链接器参数生成的程序提供一些基本保证。即使系统的负载会影响优化器可以对您的程序起作用的程度 - 一些优化器将被分配一些有限的时间 - 这不应该改变预期的行为。

请注意,虽然没有保证,但是很难推销一个编译器,它根据不相关的参数产生具有不同行为的代码,作为月亮相对于星星的位置。

答案 5 :(得分:0)

rand(3)中的{p> <stdlib.h>可以在C ++中调用,不确定“标准C ++”中包含多少C库,但肯定有一些符合标准的机制来生成随机数。

time(3)中的

<time.h>会返回当前时间;与C ++相同的故事并调用C库。