是同时(1);用C未定义行为? [英] Is while(1); undefined behavior in C?

查看:128
本文介绍了是同时(1);用C未定义行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++ 11是未定义行为,但在C了而(1); 是未定义行为?

In C++11 is it Undefined Behavior, but is it the case in C that while(1); is Undefined Behavior?

推荐答案

这是明确界定的行为。在C11新的6.8.5条款6广告已添加

It is well defined behavior. In C11 a new clause 6.8.5 ad 6 has been added

这是循环语句的控制前pression不是一个常量前pression, 156)执行没有输入/输出操作,不访问volatile对象,进行不同步在它的身上或原子操作,控制前pression,或(在for语句的情况下),其前pression-3,可以通过终止实施承担。 157)

An iteration statement whose controlling expression is not a constant expression,156) that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate.157)

157) <子>这是为了让编译器转换,如去除空循环,即使不能终止的证明。

由于您的循环控制前pression是一个常数,编译器可能不承担循环终止。这是用于那些应该永远运行下去,就像一个操作系统的反应程序。

Since the controlling expression of your loop is a constant, the compiler may not assume the loop terminates. This is intended for reactive programs that should run forever, like an operating system.

然而,对于以下循环的行为是不明确

However for the following loop the behavior is unclear

a = 1; while(a);

在影响一个编译器可以或可以不删除该环,从而导致该可终止或可以不终止程序。这是不是真的不确定的,因为它是不允许删除你的硬盘,但它避免了施工。

In effect a compiler may or may not remove this loop, resulting in a program that may terminate or may not terminate. That is not really undefined, as it is not allowed to erase your hard disk, but it is a construction to avoid.

然而有另外一个障碍,应考虑以下code:

There is however another snag, consider the following code:

a = 1; while(a) while(1);

现在,因为编译器可以假定外循环终止,内环也应该终止,要不然怎么可以在外环终止。所以,如果你有一个非常聪明的编译器则而(1); 循环,不应该终止必须有这样非终止周围环一路攀升至。如果你真的想死循环,你最好读或写在它的一些挥发性变量。

Now since the compiler may assume the outer loop terminates, the inner loop should also terminate, how else could the outer loop terminate. So if you have a really smart compiler then a while(1); loop that should not terminate has to have such non-terminating loops around it all the way up to main. If you really want the infinite loop, you'd better read or write some volatile variable in it.

为什么这一条款是不实际

这是不太可能我们的编译器公司曾经打算利用这一条款,主要是因为它是一个非常语法属性。在中间再presentation(IR),该常数与在上述实施例的可变之间的差通过不断传播容易丢失。

It is very unlikely our compiler company is ever going to make use of this clause, mainly because it is a very syntactical property. In the intermediate representation (IR), the difference between the constant and the variable in the above examples is easily lost through constant propagation.

该条款的目的是为了让编译器的编写者申请理想的转换如下所示。考虑一个不那么罕见的循环:

The intention of the clause is to allow compiler writers to apply desirable transformations like the following. Consider a not so uncommon loop:

int f(unsigned int n, int *a)
{       unsigned int i;
        int s;

        s = 0;
        for (i = 10U; i <= n; i++)
        {
                s += a[i];
        }
        return s;
}

有关建筑方面的原因(例如硬件循环),我们想这个code转变为:

For architectural reasons (for example hardware loops) we would like to transform this code to:

int f(unsigned int n, int *a)
{       unsigned int i;
        int s;

        s = 0;
        for (i = 0; i < n-9; i++)
        {
                s += a[i+10];
        }
        return s;
}

没有第6.8.5广告6这是不可能的,因为如果 N 等于 UINT_MAX 的循环可能不会终止。尽管如此,它是pretty清楚的人,这是不是这个code的作者的意图。第6.8.5广告6现在允许这种转变。然而做到这一点的方式是不是一个编译器作者作为一个无限循环的语法要求非常实用是很难维持的红外线。

Without clause 6.8.5 ad 6 this is not possible, because if n equals UINT_MAX, the loop may not terminate. Nevertheless it is pretty clear to a human that this is not the intention of the writer of this code. Clause 6.8.5 ad 6 now allows this transformation. However the way this is achieved is not very practical for a compiler writer as the syntactical requirement of an infinite loop is hard to maintain on the IR.

请注意,这是至关重要的 N I 无符号的溢出符号int 给出了不确定的行为,因此,转型是合乎情理的这个原因。高效code然而使用效益无符号,除了更大的正数范围。

Note that it is essential that n and i are unsigned as overflow on signed int gives undefined behavior and thus the transformation can be justified for this reason. Efficient code however benefits from using unsigned, apart from the bigger positive range.

另一种方法

我们的做法是将在code作家有前preSS他打算通过例如插入断言(N&LT; UINT_MAX)前循环或邮资-C类似的保证。这样编译器可以证明终止,没有依靠第6.8.5广告6。

Our approach would be that the code writer has to express his intention by for example inserting an assert(n < UINT_MAX) before the loop or some Frama-C like guarantee. This way the compiler can "prove" termination and doesn't have to rely on clause 6.8.5 ad 6.

P.S:我期待在2011年4月12日的草案paxdiablo显然是在寻找一个不同的版本,也许他的版本更新。在他的报价不断前pression的元素没有被提到。

P.S: I'm looking at a draft of April 12, 2011 as paxdiablo is clearly looking at a different version, maybe his version is newer. In his quote the element of constant expression is not mentioned.

这篇关于是同时(1);用C未定义行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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