什么是用于出租的语义的原因= a ++是不确定的? [英] What's the reason for letting the semantics of a=a++ be undefined?

查看:120
本文介绍了什么是用于出租的语义的原因= a ++是不确定的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

a = a++;

在C.不确定的行为,我问的问题是:为什么

我的意思是,我得到它可能很难提供一致的顺序事情应该做的。但是,某些编译器将永远做它在一个顺序或另一个(在给定的优化电平)。那么究竟这是为什么留给编译器来决定?

I mean, I get that it might be hard to provide a consistent order in which things should be done. But, certain compilers will always do it in one order or the other (at a given optimization level). So why exactly is this left up to the compiler to decide?

要清楚,我想知道,如果这是一个设计决策,如果是这样,是什么促使了吗?或者,也许有某种类型的硬件限制?

To be clear, I want to know if this was a design decision and if so, what prompted it? Or maybe there is a hardware limitation of some kind?

(注意:如果该问题的标题似乎不明确或不够好,然后反馈和/或更改,欢迎)

(Note : If the question title seems unclear or not good enough, then feedback and/or changes are welcome)

推荐答案

更​​新:这个问题问得<一个href=\"http://blogs.msdn.com/b/ericlippert/archive/2012/06/18/implementation-defined-behaviour.aspx\">the我在2012年6月18日博客的主题。感谢伟大的问题!

UPDATE: This question was the subject of my blog on June 18th, 2012. Thanks for the great question!

为什么呢?我想知道,如果这是一个设计决策,如果是这样,是什么促使了吗?

Why? I want to know if this was a design decision and if so, what prompted it?

您基本上要求的ANSI C设计委员会的会议纪要,我没有那些得心应手。如果您的问题只能通过明确的人谁在房间里的那一天回答,那么你将不得不找到谁是在那个房间里。

You are essentially asking for the minutes of the meeting of the ANSI C design committee, and I don't have those handy. If your question can only be answered definitively by someone who was in the room that day, then you're going to have to find someone who was in that room.

不过,我可以回答一个更广泛的问题:

However, I can answer a broader question:

是一些导致语言设计委员会留下一个合法的程序的行为的因素是什么( * )不确定或实施规定( ** )?

What are some of the factors that lead a language design committee to leave the behaviour of a legal program (*) "undefined" or "implementation defined" (**)?

第一大因素是:是在一个特定的程序的行为不同意市场上的语言有两个现有的实施如果FooCorp的编译器编译 M(阿? (),B())为呼叫,呼叫B,叫M和BarCorp的编译器编译为呼叫B,调用​​,调用M,也不是显然是正确的的行为则有强烈的动机语言设计委员会说:你俩都是正确的,并使其实现定义的行为。的特别是如果FooCorp和BarCorp都已经重新对委员会presentatives的情况。

The first major factor is: are there two existing implementations of the language in the marketplace that disagree on the behaviour of a particular program? If FooCorp's compiler compiles M(A(), B()) as "call A, call B, call M", and BarCorp's compiler compiles it as "call B, call A, call M", and neither is the "obviously correct" behaviour then there is strong incentive to the language design committee to say "you're both right", and make it implementation defined behaviour. Particularly this is the case if FooCorp and BarCorp both have representatives on the committee.

接下来的主要因素是:做的功能自然present很多不同的可能性实施例如,在C#中的查询COM prehensionEX $的编译器的分析?为做一个句法转变成一个没有查询COM prehensions,然后正常分析该程序等效节目p $ pssion中指定。很少有自由的实现采取另外的做法。

The next major factor is: does the feature naturally present many different possibilities for implementation? For example, in C# the compiler's analysis of a "query comprehension" expression is specified as "do a syntactic transformation into an equivalent program that does not have query comprehensions, and then analyze that program normally". There is very little freedom for an implementation to do otherwise.

相比之下,C#规范指出,的foreach 回路应被视为等同,而循环中尝试块,但允许执行一定的灵活性。 C#编译器被允许说,例如我知道如何更有效地落实的foreach 循环语义一个数组,并使用数组的索引功能,而不是数组转换一个序列作为规范建议它应该。

By contrast, the C# specification says that the foreach loop should be treated as the equivalent while loop inside a try block, but allows the implementation some flexibility. A C# compiler is permitted to say, for example "I know how to implement foreach loop semantics more efficiently over an array" and use the array's indexing feature rather than converting the array to a sequence as the specification suggests it should.

第三个因素是:?是特征如此复杂,其具体行为的详细分类是困难或昂贵指定 C#的规范说很少确实有关如何匿名方法,拉姆达前pressions,前pression树,动态调用,迭代器块和异步块将被执行;它只是描述了所需的语义和行为上的一些限制,并保留其余的由实现。

A third factor is: is the feature so complex that a detailed breakdown of its exact behaviour would be difficult or expensive to specify? The C# specification says very little indeed about how anonymous methods, lambda expressions, expression trees, dynamic calls, iterator blocks and async blocks are to be implemented; it merely describes the desired semantics and some restrictions on behaviour, and leaves the rest up to the implementation.

第四个因素是:请问功能强加于编译高负担分析例如,在C#中,如果您有:

A fourth factor is: does the feature impose a high burden on the compiler to analyze? For example, in C# if you have:

Func<int, int> f1 = (int x)=>x + 1;
Func<int, int> f2 = (int x)=>x + 1;
bool b = object.ReferenceEquals(f1, f2);

假设我们需要b,来是真实的。的你打算怎样来确定当两个功能是相同的的?做一个intensionality分析 - 你的函数体有相同的内容? - 是很难的,和做一个外延的分析 - 做函数具有相同的结果给出相同的输入时? - 更是难上加难。语言规范委员会应设法尽量减少这方面的一个实施团队必须解决开放性的研究问题的数量!

Suppose we require b to be true. How are you going to determine when two functions are "the same"? Doing an "intensionality" analysis -- do the function bodies have the same content? -- is hard, and doing an "extensionality" analysis -- do the functions have the same results when given the same inputs? -- is even harder. A language specification committee should seek to minimize the number of open research problems that an implementation team has to solve!

在C#这是留给因此要实现定义;编译器可以选择使他们引用自己的判断等于或不。

In C# this is therefore left to be implementation-defined; a compiler can choose to make them reference equal or not at its discretion.

第五个因素是:?请问功能强加在运行时环境负担高

例如,在C#中提领过去的数组的末尾是明确的;它产生一个数组索引是出界外例外。这个功能可以用小来实现 - 不为零,但小 - 成本在运行时。调用带有空接收器实例或虚拟方法被定义为生产空是 - 取消引用除外;再次,这可以通过一个小的,但非零成本来实现。消除未定义行为的利益支付的小成本运行。

For example, in C# dereferencing past the end of an array is well-defined; it produces an array-index-was-out-of-bounds exception. This feature can be implemented with a small -- not zero, but small -- cost at runtime. Calling an instance or virtual method with a null receiver is defined as producing a null-was-dereferenced exception; again, this can be implemented with a small, but non-zero cost. The benefit of eliminating the undefined behaviour pays for the small runtime cost.

第六个因素是:确实使得定义preclude一些主要的优化的行为?例如,C#定义的副作用的从导致副作用的线程观察时的顺序。但是,观察从另一个线程一个线程的副作用的程序的行为是实现定义除了一些特殊的副作用。 (像一种挥发性写,或进入一个锁。)如果需要,C#语言,所有的线程将观察以相同的顺序相同的副作用那么我们就必须从有效地做他们的工作限制现代处理器;现代的处理器依赖于乱序执行和复杂的缓存策略,以获得他们的高业绩水平。

A sixth factor is: does making the behaviour defined preclude some major optimization? For example, C# defines the ordering of side effects when observed from the thread that causes the side effects. But the behaviour of a program that observes side effects of one thread from another thread is implementation-defined except for a few "special" side effects. (Like a volatile write, or entering a lock.) If the C# language required that all threads observe the same side effects in the same order then we would have to restrict modern processors from doing their jobs efficiently; modern processors depend on out-of-order execution and sophisticated caching strategies to obtain their high level of performance.

这些都是想到短短的因素;有一些语言设计委员会作出功能实现定义或未定义之前争论的当然还有很多,很多其他因素。

Those are just a few factors that come to mind; there are of course many, many other factors that language design committees debate before making a feature "implementation defined" or "undefined".

现在,让我们回到你的具体的例子。

Now let's return to your specific example.

C#语言的确实的作出这样的行为严格定义();观察转让的副作用之前发生的增量的副作用。所以不可能有任何好了,这只是不可能的说法出现,因为它是可能的选择行为,并坚持下去。也没有这个preclude重大机遇优化。还有没有可能的复杂的实施策略的多样性。

The C# language does make that behaviour strictly defined(); the side effect of the increment is observed to happen before the side effect of the assignment. So there cannot be any "well, it's just impossible" argument there, because it is possible to choose a behaviour and stick to it. Nor does this preclude major opportunities for optimizations. And there are not a multiplicity of possible complex implementation strategies.

我的的,因此,我要强调,这是一个的猜测的是,C语言委员会作出的副作用排序为实现定义的行为,因为有多个在做了不同市场的编译器,没有明显更正确,而委员会却不愿告诉他们的一半,他们错了。

My guess, therefore, and I emphasize that this is a guess, is that the C language committee made ordering of side effects into implementation defined behaviour because there were multiple compilers in the marketplace that did it differently, none was clearly "more correct", and the committee was unwilling to tell half of them that they were wrong.

* )或者,有时,它的编译器!但是,让我们忽略的因素。

(*) Or, sometimes, its compiler! But let's ignore that factor.

** )未定义的行为意味着code可以做的任何的,包括删除你的硬盘。编译器不需要生成code有任何特别的行为,不需要告诉你,它是产生code。与未定义的行为。 实现定义的行为意味着编译器作者给出实施战略的选择相当大的自由度,但需要的选择一个策略用它一贯记录这样的选择

(**) "Undefined" behaviour means that the code can do anything, including erasing your hard disk. The compiler is not required to generate code that has any particular behaviour, and not required to tell you that it is generating code with undefined behaviour. "Implementation defined" behaviour means that the compiler author is given considerable freedom in choice of implementation strategy, but is required to pick a strategy, use it consistently, and document that choice.

)当从一个线程,当然,观察到的。

() When observed from a single thread, of course.

这篇关于什么是用于出租的语义的原因= a ++是不确定的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆