Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Jones D.M.The new C standard (C90 and C++).An economic and cultural commentary.2005

.pdf
Скачиваний:
19
Добавлен:
23.08.2013
Размер:
1.36 Mб
Скачать

1288 6.5.16.1 Simple assignment

C++

The C++ Standard does not explicitly make this observation.

If an attempt is made to modify the result of an assignment operator or to access it after the next sequence 1285 point, the behavior is undefined.

C90

This sentence did not appear in the C90 Standard and had to be added to C99 because of a change in the lvalue 717 definition of the term lvalue.

C++

The C++ definition of lvalue is the same as C90, so this wording is not necessary in C ++.

6.5.16.1 Simple assignment

Constraints

simple as-

One of the following shall hold:94)

1286

signment

C++

 

constraints

 

The C++ Standard does not provide a list of constraints on the operands of any assignment operator (5.17). Clause 12.8 contains the specification that leads the following difference:

C1.8 The implicitly-declared copy constructor and implicitly-declared copy assignment operator cannot make a copy of a volatile lvalue. For example, the following is valid in ISO C:

struct

X

{ int i; };

 

struct

X

x1, x2;

 

volatile

struct X x3

= {0};

x1

=

x3;

// invalid C++

x2

=

x3;

// also invalid C++

Rationale: Several alternatives were debated at length. Changing the parameter to volatile const X& would greatly complicate the generation of efficient code for class objects. Discussion of providing two alternative signatures for these implicitly-defined operations raised unanswered concerns about creating ambiguities and complicating the rules that specify the formation of these operators according to the bases and members.

the left operand has qualified or unqualified arithmetic type and the right has arithmetic type;

1287

C++

 

5.17p3

 

 

 

 

If the left operand is not of class type, the expression is implicitly converted (clause 4) to the cv-unqualified

 

 

 

type of the left operand.

 

 

 

 

 

The conversions in clause 4 do not implicitly convert enumerated types to integer types and vice versa.

1extern int glob;

2

3enum {E1, E2};

4

5void f(void)

6{

7glob = E1; /* does not affect the conformance status of the program */

8

// ill-formed

9}

v 1.0b

September 2, 2005

6.5.16.1 Simple assignment 1289

1288 — the left operand has a qualified or unqualified version of a structure or union type compatible with the type of the right;

C++

Clause 13.5.3 deals with this subject, but does not discuss this particular issue.

1289 — both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;

C++

assignment structure types

pointer qualified/unqualified versions

The C++ wording (5.17p3) requires that an implicit conversion exist.

The C++ requirements (4.4) on which implicit, qualified conversions are permitted are those described in the Smith paper (discussed elsewhere).

The pointer assignments supported by C++ are a superset of those supported by C. Source developed using a C++ translator may contain constraint violations if processed by a C translator, because it contains assignments between incompatible pointer types. The following example illustrates differences between the usages supported by C and C++ when types using two levels of pointer are declared.

742 pointer converting qualified/unqualified

1void Jon_Krom(void)

2{

3/*

4 * The issue of what is safe or unsafe is discussed elsewhere.

5* An example of case 3 is given in the standard.

6*/

7

8typedef int T; /* for any type T */

9

 

 

 

 

 

10

T

*

*

ppa

;

11

T

*

*

ppb

;

12

 

 

 

 

 

13

T

* const *

pcpa ;

14

T

* const *

pcpb ;

15

 

 

 

 

 

16

T const *

* cppa

;

17

T const *

* cppb

;

18

 

 

 

 

 

19T const * const * cpcpa ;

20T const * const * cpcpb ;

21

 

 

 

 

 

 

 

22

 

 

//

Safe

Allowed

Allowed

 

23

 

 

//

or

in

in

 

24

 

 

// Unsafe

C99

C++

 

25

 

 

// --------------------------------

 

26

ppb

= ppa ;

//

Safe

Yes

Yes

1

27

pcpb

= ppa ;

//

Safe

Yes

Yes

2

28

cppb

= ppa ;

//

Unsafe

No

No

3

29

cpcpb = ppa ;

//

Safe

No

Yes

4

30

 

 

 

 

 

 

 

31

ppb

= pcpa ;

//

Unsafe

No

No

5

32

pcpb

= pcpa ;

//

Safe

Yes

Yes

6

33

cppb

= pcpa ;

//

Unsafe

No

No

7

34

cpcpb = pcpa ;

//

Safe

No

Yes

8

35

 

 

 

 

 

 

 

36

ppb

= cppa ;

//

Unsafe

No

No

9

37

pcpb

= cppa ;

//

Unsafe

No

No

10

38

cppb

= cppa ;

//

Safe

Yes

Yes

11

39

cpcpb = cppa ;

//

Safe

Yes

Yes

12

40

 

 

 

 

 

 

 

41

ppb

= cpcpa ;

//

Unsafe

No

No

13

September 2, 2005

v 1.0b

1297 6.5.16.1 Simple assignment

42

pcpb

= cpcpa ;

//

Unsafe

No

No

14

43

cppb

=

cpcpa

;

//

Unsafe

No

No

15

44

cpcpb =

cpcpa

;

//

Safe

Yes

Yes

16

45

}

 

 

 

 

 

 

 

 

one operand is a pointer to an object or incomplete type and the other is a pointer to a qualified or

1290

unqualified version of void, and the type pointed to by the left has all the qualifiers of the type pointed to by

 

the right;

 

C++

 

5.17p3

 

 

If the left operand is not of class type, the expression is implicitly converted (clause 4) to the cv-unqualified

 

 

 

type of the left operand.

 

 

 

 

 

 

The C++ Standard only supports an implicit conversion when the left operand has a pointer to void type, 4.10p2.

1 char *pc;

2void *pv;

3

4void f(void)

5{

6 pc=pv; /* does not affect the conformance status of the program */ 7 // ill-formed

8}

or— the left operand has type _Bool and the right is a pointer.

1292

C90

Support for the type _Bool is new in C99.

C++

assignment value overlaps object

Support for the type _Bool is new in C99 and is not specified in the C ++ Standard. However, the C++ Standard does specify (4.12p1) that rvalues having pointer type can be converted to an rvalue of type bool.

Semantics

If the value being stored in an object is read from another object that overlaps in any way the storage of the 1294 first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of

a compatible type;

C++

object types 472 The C++ Standard requires (5.18p8) that the objects have the same type. Even though the rvalue may have the same type as the lvalue (perhaps through the use of an explicit cast), this requirement is worded in terms of the object type. The C++ Standard is silent on the issue of overlapping objects.

1 enum E {E1, E2};

2union {

3int m_1;

4enum E m_2;

5} x;

6

7void f(void)

8{

9x.m_1 = (int)x.m_2; /* does not change the conformance status of the program */

10

// not defined?

11

}

v 1.0b

September 2, 2005

6.5.17 Comma operator 1310

1297 94) The asymmetric appearance of these constraints with respect to type qualifiers is due to the conversion (specified in 6.3.2.1) that changes lvalues to “the value of the expression” whichand thus removes any type qualifiers from the type category of the expression that were applied to the type category of the expression (for example, it removes const but not volatile from the type intvolatile*const).

C++

Even though the result of a C++ assignment operator is an lvalue, the right operand still needs to be converted to a value (except for reference types, but they are not in C) and the asymmetry also holds in C++.

6.5.16.2 Compound assignment

Constraints

1301 For the other operators, each operand shall have arithmetic type consistent with those allowed by the corresponding binary operator.

C++

In all other cases, E1 shall have arithmetic type.

5.15p7

 

 

 

Those cases where objects may not have some arithmetic type when appearing as operands to operators (i.e., floating types with the shift operators) are dealt with using the equivalence argument specified earlier in 5.15p7.

Semantics

6.5.17 Comma operator

Semantics

footnote 94

1305

1308

there is a sequence point after its evaluation.

C++

All side effects (1.9) of the left expression, except for the destruction of temporaries (12.2), are performed before the evaluation of the right expression.

The discussion on the function-call operator is applicable here.

If an attempt is made to modify the result of a comma operator or to access it after the next sequence point, the behavior is undefined.

comma operator sequence point

5.18p1

1017 function call sequence point

C90

 

This sentence did not appear in the C90 Standard and had to be added to C99 because of a change in the

 

 

definition of the term lvalue.

 

717 lvalue

 

C++

 

 

 

The C++ definition of lvalue is the same as C90, so this wording is not necessary in C ++.

717 lvalue

 

 

 

 

1310 95) A comma operator does not yield an lvalue.

 

footnote

 

 

 

94

 

C++

 

comma operator

 

 

lvalue

 

 

 

 

 

 

5.18p1

 

September 2, 2005

v 1.0b

 

1314 6.6 Constant expressions

. . . ; the result is an lvalue if its right operand is.

1#include <stdio.h>

2

3void DR_188(void)

4{

5char arr@lsquare[]100@rsquare[];

6

7if (sizeof(0, arr) == sizeof(char *))

8printf("A C translator has been used\n");

9else

10if (sizeof(0, arr) == sizeof(arr))

11printf("A C++ translator has been used\n");

12else

13printf("Who knows why we got here\n");

14}

15

16void f(void)

17{

18int loc;

19

20(2, loc)=3; /* constraint violation */

21// conforming

22}

6.6Constant expressions

Description

A constant expression can be evaluated during translation rather than runtime, and accordingly may be used 1313 in any place that a constant may be.

C++

The C++ Standard says nothing about when constant expressions can be evaluated. It suggests (5,19p1) places where such constant expressions can be used. It has proved possible to write C++ source that require translators to calculate relatively complicated functions. The following example, from Veldhuizen,[6] implements the pow library function at translation time.

1template<int I, int Y>

2struct ctime_pow

3{

4static const int result = X * ctime_pow<X, Y-1>::result;

5};

6

7// Base case to terminate recursion

8template<int I>

9struct ctime_pow<X, 0>

10{

11static const int results =- 1;

12};

13

14 const int x = ctime_pow<5, 3>::result; // assign five cubed to x

 

Constraints

 

 

 

 

constant ex-

 

Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, 1314

pression

 

except when they are contained within a subexpression that is not evaluated.96)

not contain

 

 

 

v 1.0b

September 2, 2005

6.6 Constant expressions 1320

C90

. . . they are contained within the operand of a sizeof operator.53)

With the introduction of VLAs in C99 the result of the sizeof operator is no longer always a constant expression. The generalization of the wording to include any subexpression that is not evaluated means that nonconstant subexpressions can appear as operands to other operators (the logical-AND, logical-OR, and conditional operators). For instance, 0 || f() can be treated as a constant expression. In C90 this expression, occurring in a context requiring a constant, would have been a constraint violation.

C++

Like C90, the C++ Standard only permits these operators to occur as the operand of a sizeof operator.

See C90 difference.

sizeof result of

1315 Each constant expression shall evaluate to a constant that is in the range of representable values for its type.

C++

The C++ Standard does not explicitly specify an equivalent requirement.

Semantics

1317 If a floating expression is evaluated in the translation environment, the arithmetic precision and range shall be at least as great as if the expression were being evaluated in the execution environment.

C++

This requirement is not explicitly specified in the C ++ Standard.

1318 An integer constant expression97) shall have integer type and shall only have operands that are integer con-

integer con-

stants, enumeration constants, character constants, sizeof expressions whose results are integer constants,

stant expression

and floating constants that are the immediate operands of casts.

 

C++

 

 

 

 

 

 

 

5.19p1

 

 

. . . , const variables or static data members of integral or enumeration types initialized with constant expres-

 

 

 

 

 

 

 

sions (8.5), . . .

 

 

 

 

 

 

For conforming C programs this additional case does not cause a change of behavior. But if a C++ translator

 

is being used to develop programs that are intended to be conforming C, there is the possibility that this

 

construct will be used.

 

1

const int ten = 10;

 

2

 

 

 

3

char arr@lsquare[]ten@rsquare[]; /* constraint violation */

 

4

// does not change the conformance status of the program

 

1320 More latitude is permitted for constant expressions in initializers.

C++

5.19p2

September 2, 2005

v 1.0b

1335 6.6 Constant expressions

Other expressions are considered constant-expressions only for the purpose of non-local static object initialization (3.6.2).

footnote

96) The operand of a sizeof operator is usually not evaluated (6.5.3.4).

1324

96

C90

 

 

 

 

 

 

 

 

 

 

The operand of a sizeof operator is not evaluated (6.3.3.4) and thus any operator in 6.3 may be used.

 

 

 

 

 

 

 

 

 

 

Unless the operand contains a VLA, which is new in C99, it will still not be evaluated.

 

 

C++

 

 

The operand is never evaluated in C++. This difference was needed in C99 because of the introduction of

 

 

variable length array types.

 

 

 

 

 

 

— an address constant for an object type plus or minus an integer constant expression.

1328

 

C++

 

 

The C++ language requires that vendors provide a linker for a variety of reasons; for instance, support for

 

 

name mangling.

 

 

 

 

 

address constant

An address constant is a null pointer, a pointer to an lvalue designating an object of static storage duration,

1331

 

or a pointer to a function designator;

 

C90

The C90 Standard did not explicitly state that the null pointer was an address constant, although all known implementations treated it as such.

C++

The C++ Standard does not include (5.19p4) a null pointer in the list of possible address constant expressions. Although a null pointer value is listed as being a constant-expression (5.19p2). This difference in terminology does not appear to result in any differences.

constant expression

other forms

it shall be created explicitly using the unary & operator or an integer constant cast to pointer type, or implicitly

1332

by the use of an expression of array or function type.

 

C90

 

Support for creating an address constant by casting an integer constant to a pointer type is new in C99.

 

However, many C90 implementations supported this usage. It was specified as a future change by the

 

response to DR #145.

 

C++

 

Like C90, the C++ Standard does not specify support for an address constant being created by casting an

 

integer constant to a pointer type.

 

 

 

 

An implementation may accept other forms of constant expressions.

1334

C++

 

The C++ Standard does not given explicit latitude for an implementation to accept other forms of constant expression.

v 1.0b

September 2, 2005

6.7 Declarations 1339

1335 The semantic rules for the evaluation of a constant expression are the same as for nonconstant expressions.98)

C++

The C++ Standard does not explicitly state this requirement, in its semantics rules, for the evaluation of a constant expression.

constant expression

semantic rules

1337 98) Thus, in the following initialization,

static int i = 2 || 1 / 0;

the expression is a valid integer constant expression with value one.

C++

The C++ Standard does not make this observation.

6.7 Declarations

1338

declaration:

declaration-specifiers init-declarator-listopt ; declaration-specifiers:

storage-class-specifier declaration-specifiersopt type-specifier declaration-specifiersopt type-qualifier declaration-specifiersopt function-specifier declaration-specifiersopt

init-declarator-list: init-declarator

init-declarator-list , init-declarator

init-declarator:

declarator

declarator = initializer

C90

Support for function-specifier is new in C99.

C++

The C++ syntax breaks declarations down into a number of different categories. However, these are not of consequence to C, since they involve constructs that are not available in C.

The nonterminal type-qualifier is called cv-qualifier in the C++ syntax. It also reduces through type-specifier, so the C++ abstract syntax tree is different from C. However, sequences of tokens corresponding to C declarations are accepted by the C++ syntax.

The C++ syntax specifies that declaration-specifiers is optional, which means that a semicolon could syntactically be interpreted as an empty declaration (it is always an empty statement in C). Other wording requires that one or the other always be specified. A source file that contains such a construct is not ill-formed and a diagnostic may not be produced by a translator.

Constraints

1339 A declaration shall declare at least a declarator (other than the parameters of a function or the members of a structure or union), a tag, or the members of an enumeration.

C90

footnote 98

declaration syntax

declaration shall declare identifier

6.5

September 2, 2005

v 1.0b

4 typedef I I;
5

1343 6.7 Declarations

A declaration shall declare at least a declarator, a tag, or the members of an enumeration.

The response to DR #155 pointed out that the behavior was undefined and that a diagnostic need not be issued for the examples below (which will cause a C99 implementation to issue a diagnostic).

1struct { int mbr; }; /* Diagnostic might not appear in C90. */

2 union { int mbr; }; /* Diagnostic might not appear in C90. */

declaration only one if no

linkage

Such a usage is harmless in that it will not have affected the output of a program and can be removed by simple editing.

If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or 1340 type specifier) with the same scope and in the same name space, except for tags as specified in 6.7.2.3.

C++

C++

one definition rule

This requirement is called the one definition rule (3.2) in C++. There is no C++ requirement that a typedef name be unique within a given scope. Indeed 7.1.3p2 gives an explicit example where this is not the case (provided the redefinition refers to the type to which it already refers).

A program, written using only C constructs, could be acceptable to a conforming C++ implementation, but not be acceptable to a C implementation.

1typedef int I;

2typedef int I; // does not change the conformance status of the program

3/* constraint violation */

// does not change the conformance status of the program /* constraint violation */

declarations refer to same object declarations refer to same function

3.5p10

All declarations in the same scope that refer to the same object or function shall specify compatible types.

1341

C++

After all adjustments of types (during which typedefs (7.1.3) are replaced by their definitions), the types specified by all declarations referring to a given object or function shall be identical, except that declarations for an array object can specify array types that differ by the presence or absence of a major array bound (8.3.4). A violation of this rule on type identity does not require a diagnostic.

C++ requires identical types, while C only requires compatible types. A declaration of an object having an enumerated type and another declaration of the same identifier, using the compatible integer type, meets the C requirement but not the C++ one. However, a C++ translator is not required to issue a diagnostic if the declarations are not identical.

1enum E {E1, E2};

2

3extern enum E glob_E;

4extern int glob_E; /* does not change the conformance status of the program */

5

// Undefined behavior, no diagnostic required

6

7extern long glob_c;

8extern long double glob_c; /* Constraint violation, issue a diagnostic message */

9

// Not required to

issue a diagnostic message

Semantics

v 1.0b

September 2, 2005

 

6.7 Declarations

1346

 

 

 

 

 

 

 

 

 

1343 A definition of an identifier is a declaration for that identifier that:

definition

C++

identifier

 

The C++ wording is phrased the opposite way around to that for C:

 

A declaration is a definition unless . . .

The C++ Standard does not define the concept of tentative definition, which means that what are duplicate tentative definitions in C (a permitted usage) are duplicate definitions in C++ (an ill-formed usage).

3.1p2

tentative definition

1 int glob;

/* a tentative definition */

2// the definition

3

 

4

int glob = 5; /* the definition */

5

// duplicate definition

1344 — for an object, causes storage to be reserved for that object;

 

 

object

C++

 

 

reserve storage

 

 

 

The C++ Standard does not specify what declarations are definitions, but rather what declarations are not

definitions:

 

 

 

 

 

 

 

3.1p2

 

. . . , it contains the extern specifier (7.1.1) or a linkage-specification

24)

(7.5) and neither an initializer

 

 

 

nor a function-body, . . .

 

 

 

 

 

 

 

7p6

 

 

 

 

 

An object declaration, however, is also a definition unless it contains the

extern specifier and has no initializer

 

 

 

(3.1).

 

 

 

 

 

 

 

 

1345 — for a function, includes the function body; 99)

C++

The C++ Standard does not specify what declarations are definitions, but rather what declarations are not definitions:

3.1p2

A declaration is a definition unless it declares a function without specifying the function’s body (8.4), . . .

1346 — for an enumeration constant or typedef name, is the (only) declaration of the identifier.

C90

The C90 Standard did not specify that the declaration of these kinds of identifiers was also a definition, although wording in other parts of the document treated them as such. The C99 document corrected this defect (no formal DR exists). All existing C90 implementations known to your author treat these identifiers as definitions; consequently, no difference is specified here.

September 2, 2005

v 1.0b

Соседние файлы в предмете Электротехника