Detailed explanation of the order of priority for C/C ++ expressions

Source: Internet
Author: User

The order in which expressions are evaluated is different from the combination and priority of operations. The following is a classic example, which is explicitly mentioned by the three standards of ISO C99/C 98/03: The result is unspecified.
I = I 1; // The behavior is unspecified
Before introducing the concept, Let's explain its results. This expression contains three subexpressions ):
E1 = I
E2 = e1 1
I = e2
These three subexpressions have no sequence point, and I = e3 are all side effect expressions. Because there is no sequence point, the language does not guarantee the order of these two side effects.

Even worse, if I is a built-in type and is rewritten more than once before the next sequence point, the result is undefined! For example, if:

Int I = 0x1000fffe;
I = I 1; // The result is undefined !!

You may think that the result of adding 1 or 2 is worse-the result may be 0x1001ffff. Its high byte accepts the content of one side effect, while the low byte accepts the content of another side effect! If I is a pointer, it will easily cause program crash.

Why? For compiler providers, unconfirmed order plays an important role in optimization. For example, a common optimization strategy is "Reducing register occupation and temporary objects ". The compiler can reorganize the evaluation of expressions so that additional registers and temporary variables are not used as much as possible. More strictly speaking, even compiler providers cannot completely serialize commands (for example, they cannot strictly define the read and write orders), because the CPU itself has the right to modify the order of commands, in order to achieve a higher speed.

The following terms are subject to ISO C99 and C 03. The translated name is a reference with a reference to the original term. If any explanation is inappropriate or incorrect, please correct it.

--------------------------------------------------------------------------------

Expressions have two functions. Each expression generates a value and may contain side effects. For example, it may modify some values.

The core of a rule is the sequence point [C99 6.5 Expressions Clause 2] [C 03 5 Expressions overview Clause 4]. This is a settlement point. The language requires that the evaluation and side effects (except the destruction of temporary objects) on this side be completed in order to enter the following part. Most expressions in C/C do not have sequence points. Only the following five expressions are supported:

1 function. Before a function is called, there is a value order point.

2 & | and? : These three expressions contain logic. After the left-side logic is complete, there is a value order point.

3. Comma expression. The left side of the comma is an order of values.

Note that they all have only one order of value. After the operation on the Right of 2 and 3 ends, there is no order of value.

Between two ordered points, the order of the subexpression evaluation and side effects is uncertain. If the result of the Code is related to the order of evaluation and side effects, we call this Code unspecified behavior ). In addition, if you perform more than one write operation on a built-in type during the period, it is an undefined behavior (undefined behavior) -- we know, the best consequence of undefined behavior is to let your program collapse immediately.

N = n; // two side effects, which are undefined for built-in objects
Almost all expressions have unknown order of evaluation. For example, in the following addition, the call sequence of f1 f2 f3 is arbitrary:

N = f1 () f2 () f3 (); // The Call Sequence of f1 f2 f3 is arbitrary.
The function only has a value order point before the actual call. Therefore, these questions are common in early C language textbooks:

Printf ("% d", -- a B, -- B a); // -- a B and -- B a subexpressions. The order of evaluation is uncertain.
Oh, God, maybe even some undefined behavior? So it is the best countermeasure to never write implementation-related code. Even if there are uncertain behaviors (for example, when a function is called), the compiler can do this as long as there is no sequence point. Some people think that the evaluation of function call parameters is related to the order of the incoming stack, which is misleading. This is what Zhuge Liang said after the event:
Void f (int i1, int i2, int i3, int i4 ){
Cout <i1 <i2 <i3 <i4 <endl;
}
Int main (){
Int I = 0;
F (I, I );
}

There are four expressions to evaluate, and each expression has a negative effect. What are the results of these eight operations in any order? Undefined.

Use VC7.1 Debug and Release to test the same Code separately. The results are different:

0 0 0 0 [release]
3 2 1 0 [debug]

In fact, given the previous discussion, if we change some other initial values, there may even be misoperations and strange results.

Let's take a look at other typical examples in the C/C standard:

[C99] 6.5.2.2 Function call
Clause 12 EXAMPLE is in the following function call:

(* Pf [f1 ()]) (f2 (), f3 () f4 ())

Functions f1 f2 f3 and f4 may be called in any order. However, all side effects must be completed before calling the function pointer returned by pf [f1.

[C 03] 5 Introduction to Expressions 4

I = v [I]; // the behavior is unspecified
I = 7, I, I; // I becomes 9 (the value assignment expression has a higher priority than the comma expression)

I = I 1; // the behavior is unspecified
I = I 1; // the value of I is incremented

--------------------------------------------------------------------------------

More than tive C warns us not to overload &, | and operator [MEC, clause 7]. Why?

Take the comma operator as an example. Each comma has a value order on the left. If ar is a common object, the following method is unambiguous:
Ar [I], I;

However, if ar [I] returns A class A object or reference, and it reloads operator, the result is not good. The preceding statement is actually a function call:
Ar [I]. operator, (I );

In C/C, the function only has a value order point before the call. Therefore, the order of ar [I], I, And I side effects is arbitrary. This can cause confusion.

What's more terrible is that heavy load & |. Everyone is used to its speed-to-death algorithm: If the left side has determined the final result, the right side will not be evaluated. In addition, we rely heavily on this behavior. For example, C-style string copy is often written as follows:
While (p & * p)
* Pd = * p;

If p is 0, * p's behavior is undefined and may crash the program. The order of & values avoids this. However, if we reload &, it is equal to the following practice:
Exp1. operator & (exp2)
Now it's not just about confusion in the evaluation. No matter what the exp1 result is, exp2 will be evaluated.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.