Sheen Space

C++ Standard Notes – Program Execution

leave a comment »

C++ Standard (Draft n3126)

Program Execution (1.9)

Context of this section is single-thread execution. Single-thread execution environment consists of full-expressions.

1. Full-expression

A full-expression is an expression that is not a subexpression of another expression.
Normally a full-expression is a single line of C++ code that ends with ‘;’, or expression in conditional clause like “if”, “while”. In contrast, a subexpression is always part of a full-expression.

If a language construct is defined to produce an implicit call of a function, a use of the language construct is considered to be an expression for the purposes of this definition.
For example, call of casting operator, or class constructor function.

A call to a destructor generated at the end of the lifetime of an object other than a temporary object is an implicit full-expression.
This means normal implicit destructor call is full expression. A temporary object may be created and destroyed, in situation like function argument value computation. In this case, destructor call to the temporary object is subexpression.

Conversions applied to the result of an expression in order to satisfy the requirements of the language construct in which the expression appears are also considered to be part of the full-expression.
This includes glvalue-to-prvalue conversion, array-to-pointer conversion, and so on.

2. Evaluation of expression

Evaluation of an expression (or a sub-expression) in general includes both value computations and initiation of side effects.
Side effect itself is not part of evaluation of expression. Side effect can be understood as any action that changes memory content or triggers external I/O.

The execution of unsequenced evaluations can overlap.
How to understand this? Because every evaluation can be translated into multiple assembly codes, assembly codes from unsequenced evaluations can interleave.

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.(1) The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.(2) If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.(3)
We can understand this by understanding example given below it:

void f(int, int);
void g(int i, int* v) {
	i = v[i++]; // the behavior is undefined
	// It is undefined because of statement (3). On right side of assignment, i++ has side effect of modifying i, and i is also used in subscripting expression(5.2.1) v[...].

	i = 7, i++, i++; // i becomes 9
	// This is equivalently (i = 7), i++, i++. It is well-formed because comma operator(5.18) is sequenced from left to right.

	i = i++ + 1; // the behavior is undefined
	// It is undefined because of statement (3). This is same as first example, because subscripting operator is essentially pointer + integral type.

	i = i + 1; // the value of i is incremented
	// It is well-formed. No side effect.

	f(i = -1, i = -1); // the behavior is undefined
	// It is undefined because of statement (1) and (3). But behaviour is expected in reality because both side effects assign -1 to i.

Link below is a thread discussion about why behaviour of i = v[i++] is undefined:

In my opinion, the reasoning there is overkilling and sometimes wrong.


Written by Ying

05/10/2010 at 15:54

Posted in C++, Programming, Technology

Tagged with

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: