# The New C Standard- P12

Chia sẻ: Thanh Cong | Ngày: | Loại File: PDF | Số trang:100

0
87
lượt xem
4

## The New C Standard- P12

Mô tả tài liệu

Tham khảo tài liệu 'the new c standard- p12', công nghệ thông tin, kỹ thuật lập trình phục vụ nhu cầu học tập, nghiên cứu và làm việc hiệu quả

Chủ đề:

Bình luận(0)

Lưu

## Nội dung Text: The New C Standard- P12

1. 6.5.10 Bitwise AND operator 1238 Commentary 702 operators The rationale for performing these conversions is a general one that is not limited to the operands of the cause conversions arithmetic operators. C++ The following conversion is presumably performed on the operands. The usual arithmetic conversions are performed; 5.11p1 Common Implementations If one of the operands is positive and has a type with lower rank than the other operand, it may be possible to make use of processor instructions that operate on narrower width values. (Converting the operand to the greater rank will cause it to be zero extended, which will cancel out any ones in the other operand.) Unless both operands are known to be positive, there tend to be few opportunities for optimizing occurrences of the ^ and | operators (because of the possibility that the result may be affected by an increase in value representation bits). Coding Guidelines Unless both operands have the same type, which also has a rank at least equal to that of int, these conversions will increase the number of value representation bits in one or both operands. Given that the binary & operator is deﬁned to work at the bit level, developers have to invest additional effort in considering the effects of the usual arithmetic operands on the result of this operator. A probabilistic argument could be used to argue that of all the bitwise operators the & operator has the lowest probability of causing a fault through an unexpected increase in the number of value representation bits. For instance, the probability of both operands having a negative value (needed for any additional bits to be set in the result) is lower than the probability of one operand having a negative value (needed for a bit to be set in the result of the ^ and | operators). Unless the operands have a bit-set role, the guideline recommendation dealing with use of representation 945 bit-set role 569.1 represen- information is applicable here. tation in- formation using 1237 The result of the binary & operator is the bitwise AND of the operands (that is, each bit in the result is set if and only if each of the corresponding bits in the converted operands is set). Commentary This information is usually expressed in tabular form. 0 1 0 0 0 1 0 1 Common Implementations The Unisys A Series[1423] uses signed magnitude representation. If the operands have an unsigned type, the bit used to represent the sign in signed types, which is present in the object representation on this processor, does not take part in the binary & operation. If the operands have a signed type, the sign bit does take part in the bitwise-AND operation. Coding Guidelines Although the result of the bitwise-AND operator is the common type derived from the usual arithmetic 706 usual arith- conversions, for the purpose of these guideline recommendations its role is the same as that of its operands. metic conver- sions 1352 object role 1238 92) Two objects may be adjacent in memory because they are adjacent elements of a larger array or adjacent footnote 92 members of a structure with no padding between them, or because the implementation chose to place them so, even though they are unrelated. June 24, 2009 v 1.2
2. 1240 6.5.11 Bitwise exclusive OR operator array 526 Commentary contiguously allocated set By deﬁnition elements of an array are contiguous and the standard speciﬁes the relative order of members of objects structure 1206 and their possible padding. Some implementations treat objects deﬁned by different declarations in the same members later compare later way as the declaration of members in a structure deﬁnition. For instance, assigning the same relative offsets structure 1424 unnamed padding to objects local to a function deﬁnition as they would the equivalent member declarations in a structure type. storage 1354 layout The issue of the layout of objects in storage is discussed elsewhere. This footnote lists all the cases where objects may be adjacent in memory. C90 The C90 Standard did not discuss these object layout possibilities. C++ The C++ Standard does not make these observations. Other Languages Most languages do not get involved in discussing this level of detail. Common Implementations Most implementations aim to minimize the amount of padding between objects. In many cases objects deﬁned in block scope are adjacent in memory to objects deﬁned textually adjacent to them in the source code. If prior invalid pointer operations (such as accesses outside array bounds) produced undeﬁned behavior, 1239 subsequent comparisons also produce undeﬁned behavior. Commentary This describes a special case of undeﬁned behavior. (It is called out because, in practice, it is more likely to occur for values having pointer types than values having integer types.) Once undeﬁned behavior has occurred, any subsequent operation can also produce undeﬁned behavior. The standard does not limit the scope of undeﬁned behaviors to operations involving operands that cause the initial occurrence. Common Implementations On many implementations the undeﬁned behavior that occurs when additive operations, on values having an integer type, overﬂow is symmetrical. That is, an overﬂow in one direction can be undone by an overﬂow in the other direction (e.g., INT_MAX+2-2 produces the same result as INT_MAX-2+2). On implementations pointer 590 segmented for processors using a segmented architecture this symmetrical behavior may not occur, for values having architecture pointer types, because of internal details of how pointer arithmetic is handled on segment boundaries. arithmetic 687 On some processors additive operations, on integer or pointer types, saturate. In this case the undeﬁned saturated behavior is not symmetrical. C90 The C90 Standard did not discuss this particular case of undeﬁned behavior. 6.5.11 Bitwise exclusive OR operator exclusive-OR-expression: 1240 AND-expression exclusive-OR-expression ^ AND-expression Commentary The ^ operator can be replaced by a sequence of equivalent bitwise operators; for instance, x ^ y can be written (x & (~y)) | ((~x) & y). However, most processors contain a bitwise exclusive-OR instruction and thus this operator is included in C. Being able to represent a bitwise operator using an equivalent sequence of other operators is not necessarily an argument against that operator being included in C. It is v 1.2 June 24, 2009
3. 6.5.11 Bitwise exclusive OR operator 1242 possible to represent any boolean expression using a sequence of NAND (not and, e.g., !(x & y)) operators; for instance, !x becomes x NAND x, x & y becomes (x NAND y) NAND (x NAND y), and so on. Although this equivalence may be of practical use in hardware design (where use of mass-produced circuits performing a single boolean operation can reduce costs), it is not applicable to software. Other Languages Languages that support bitwise operations usually support an exclusive-OR operator. The keyword xor is sometimes used to denote this operator. The ^ character is used as a token to indicate pointer indirection in Pascal and Ada. Coding Guidelines The exclusive-OR operator is not encountered in everyday life. There is no English word or phrase that 1256 logical-OR- expresses its semantics. The everyday usage discussed in the subclause on the logical-OR operator is based expression syntax on selecting between two alternatives (e.g., either one or the other which only deals with two of the four possible combinations of operand values). Because of the lack of everyday usage, and because it does not occur often within C source (compared with bitwise-AND and bitwise-OR (see Table 912.2)) it is to be expected that developers will have to expend more effort in comprehending the consequences of this operator when it is encountered in source code. The greater cognitive cost associated with use of the exclusive-OR operator is not sufﬁcient to recommend against its use. Developers need to be able to make use of an alternative that has a lower cost. While the behavior of the exclusive-OR operator can be obtained by various combinations of other bitwise operators, it seems unlikely that the cost of comprehending any of these sequences of operators will be less than that of the operator they replace. If the exclusive-OR operator appears within a more complicated boolean expression 1248.1 boolean it may be possible to rewrite that expression in an alternative form. Rewriting an expression can increase expression minimize effort the cognitive effort needed for readers to map between source code and the application domain (i.e., if the conditions in the application domain are naturally expressed in terms of a sequence of operators that include exclusive-OR). The cost/beneﬁt of performing such a rewrite needs to be considered on a case by case basis. Example The ^ operator is equivalent to the binary + operator if its operands do not have any set bits in common. This property can be used to perform simultaneous addition on eight digits represented in packed BCD[698] (i.e., four bits per digit). 1 int BCD_add(a, b) 2 { 3 int t1 = a + 0x06666666, 4 t2 = t1 + b, 5 t3 = t1 ^ b, 6 t4 = t2 ^ t3, 7 t5 = ~t4 & 0x11111110, 8 t6 = (t5 >> 2) | (t5 >> 3); 9 return t2 - t6; 10 } Usage The ^ operator represents 1.2% of all occurrences of bitwise operators in the visible source of the .c ﬁles. Constraints 1241 Each of the operands shall have integer type. Commentary 1235 & binary The discussion for the various subsections is the same as those for the bitwise AND operator. operand type Semantics June 24, 2009 v 1.2
4. 1244 6.5.12 Bitwise inclusive OR operator ^ The usual arithmetic conversions are performed on the operands. 1242 operands con- verted Commentary & binary 1236 operands The discussion in the various subsections is the same as that for the bitwise AND operator. converted The result of the ^ operator is the bitwise exclusive OR of the operands (that is, each bit in the result is set if 1243 and only if exactly one of the corresponding bits in the converted operands is set). Commentary This information is usually expressed in tabular form. 0 1 0 0 1 1 1 0 Common Implementations The Unisys A Series[1423] uses signed magnitude representation. If the operands have an unsigned type, the sign bit is not affected by the bitwise complement operator. If the operands have a signed type, the sign bit does take part in the bitwise complement operation. The bitwise exclusive-OR instruction is sometimes generated, by optimizers, to swap the contents of two registers, without using a temporary register (as shown in the Example below). Coding Guidelines Although the result of the bitwise exclusive-OR operator is the common type derived from the usual arithmetic usual arith- 706 metic con- conversions, for the purpose of these guideline recommendations its role is the same as that of its operands. versions object 1352 role Example 1 #define SWAP(x, y) (x=(x ^ y), y=(x ^ y), x=(x ^ y)) 2 #define UNDEFINED_SWAP(x, y) (x ^= y ^= x ^= y) /* Requires right to left evaluation. */ 6.5.12 Bitwise inclusive OR operator inclusive-OR- expression syntax 1244 inclusive-OR-expression: exclusive-OR-expression inclusive-OR-expression | exclusive-OR-expression Commentary AND- 1234 expression The discussion on AND-expression is applicable here. syntax Coding Guidelines The | and || operators differ from their corresponding AND operators in that the zero/nonzero status of their result is always the same, even though the actual result values are likely to differ. 0x10 | 0x01 ⇒ 0x11 0x10 || 0x01 ⇒ 1 While it is possible to use either operators in a context where the result is compared against zero, the role 1234 guideline recommendation dealing with matching an operator to the role of its result still applies. The pattern operand matching of operator context usage (see Table 1244.1) is similar to that of the two AND operators. v 1.2 June 24, 2009
5. 6.5.12 Bitwise inclusive OR operator 1247 Table 1244.1: Occurrence of the | and || operator (as a percentage of all occurrences of each operator; the parenthesized value is the percentage of all occurrences of the context that contains the operator). Based on the visible form of the .c ﬁles. Context | || if control-expression 8.8 ( 0.7) 86.0 ( 6.9) other contexts 90.7 (—) 11.9 (—) while control-expression 0.3 ( 0.5) 1.9 ( 2.7) for control-expression 0.0 ( 0.0) 0.3 ( 0.2) switch control-expression 0.1 ( 0.3) 0.0 ( 0.0) Constraints 1245 Each of the operands shall have integer type. Commentary 1235 & binary The discussion for the various subsections is the same as those for the bitwise AND operator. operand type Semantics 1246 The usual arithmetic conversions are performed on the operands. Commentary 1242 ^ The discussion in the various subsections is the same as that for the bitwise exclusive-OR operator. operands con- verted 1247 The result of the | operator is the bitwise inclusive OR of the operands (that is, each bit in the result is set if and only if at least one of the corresponding bits in the converted operands is set). Commentary This information is usually expressed in tabular form. 0 1 0 0 1 1 1 1 Common Implementations The Unisys A Series[1423] uses signed magnitude representation. If the operands have an unsigned type, the sign bit is not affected by the bitwise-OR operator. If the operands have a signed type, the sign bit does take part in the bitwise-OR operation. binary | × × decimal notation • • hexadecimal notation 100 ×• • × • • • Occurrences × •• • • × × • • ×• • • • • × 10 ×• •× • •× × •• • • •× • • ×• • • ×• × ×• ••• • • ••• • • ••• • • • ×× × • • ×• • × × 1 •×• ×••••×× ••• × • • •• • ××• ×• •• • • •• •• •• ••× 0 16 32 64 100 128150 200 255 Numeric value Figure 1244.1: Number of integer-constants having a given value appearing as the right operand of the bitwise-OR operator. Based on the visible form of the .c ﬁles. June 24, 2009 v 1.2
6. 1248 6.5.13 Logical AND operator Coding Guidelines Although the result of the bitwise inclusive-OR operator is the common type derived from the usual arithmetic usual arith- 706 metic con- conversions, for the purpose of these guideline recommendations its role is the same as that of its operands. versions object 1352 role 6.5.13 Logical AND operator logical-AND- expression syntax 1248 logical-AND-expression: inclusive-OR-expression logical-AND-expression && inclusive-OR-expression Commentary The relative precedence of the binary && and || operators is the same as that of the binary & and | operators. Other Languages In many languages the logical-AND operator has higher precedence than the logical-OR operator. In a few languages (Ada, Fortran which uses the keyword .AND.), they have the same precedence. Ada supports bitwise 1234 two kinds of logical-AND operations: and and and then, the latter having the same semantics as the & logical-AND operator in C (short-circuit evaluation). These operators also have the same precedence as the logical-OR and logical-XOR operators. Coding Guidelines AND- 1234 expression The issue of swapping usages of the & and && operators is discussed elsewhere. syntax There are a number of techniques for simplifying expressions involving boolean values. One of the most commonly used methods is the Karnaugh map.[725] (For equations involving more than ﬁve operands, the Quine-McCluskey technique[1388] may be more applicable; this technique is also capable of being automated.), while some people prefer algebraic manipulation (refer to Table 1248.1). Although simpliﬁcation may lead to an expression that requires less reader effort to comprehend as a boolean expression, the resulting expression may require more effort to map to the model of the application domain being used. For instance, (A && (!B)) || ((!A) && B) can be simpliﬁed to A ^ B (assuming A and B only take the values 0 and 1, otherwise another operation is required). However, while the use of the exclusive-OR operator results in a visually simpler expression, developers have much less experience dealing with it than the other bitwise and logical operators. There is also the possibility that, for instance, the expression (A && (!B)) occurs in other places within the source and has an easily-deduced meaning within the framework of the application model. mind Logical operators are part of mathematical logic. Does the human mind contain special circuitry that logical operator performs this operation, just like most processors contain a group of transistors that perform this C operation? Based on experimental observations, the answer would appear to be no. So how does the human mind handle the logical-AND operation? One proposal is that people learn the rules of this operator by rote so that they can later be retrieved from memory. The result of a logical operation is then obtained by evaluating each operand’s condition to true or false and performing a table lookup using previously the learned logical-AND table to ﬁnd the result. Such an approach relies on short-term memory, and the limited capacity of short-term memory offers one explanation of why people are poor at evaluating moderately complex logical operators in their head. There is insufﬁcient capacity to hold the values of the operands and the intermediate results. The form of logical deduction that is needed in comprehending software rarely occurs in everyday life. People’s ability to solve what appear to be problems in logic does not mean that the methods of boolean mathematics are used. A number of other proposals have been made for how people handle logical problems in everyday life. One is that the answers to the problems are simply remembered; after many years of life experience, people accumulate a store of knowledge on how to deal with different situations. Studies have found that belief in a particular statement being true can cause people to ignore its actual status as a mathematical expression (i.e., people believe what they consider to be true rather than logically evaluating v 1.2 June 24, 2009
7. 6.5.13 Logical AND operator 1248 the true status of an expression). Estimating developers’ performance at handling logical expressions therefore involves more than a model of how they process mathematical logic. While minimizing the number of operands in a boolean expression may have appeal to mathematically oriented developers, the result may be an expression that requires more effort to comprehend. It is not yet possible to calculate the reader effort required to comprehend a particular boolean expression. For this reason the following guideline recommendation relies on the judgment of those performing the code review. Rev 1248.1 Boolean expressions shall be written in a form that helps minimize the effort needed by readers to comprehend them. A comment associated with the simpliﬁed expression can be notated in at least two ways: using equations or by displaying the logic table. Few developers are sufﬁciently practiced at boolean algebra to be able to ﬂuently manipulate expressions; a lot of thought is usually required. A logic table highlights all combinations of operands and, for small numbers of inputs, is easily accommodated in a comment. Table 1248.1: Various identities in boolean algebra expressed using the || and && operators. Use of these identities may change the number of times a particular expression is evaluated (which is sometimes the rationale for rewriting it). The relative order in which expressions are evaluated may also change (e.g., when A==1 and B==0 in (A && B) || (A && C) the order of evaluation is A⇒ B⇒ A⇒ C, but after use of the distributive law the order becomes A⇒ B⇒ C). Relative Order Preserved Expression ⇒ Alternative Representation Distributive laws no (A && B) || (A && C) ⇒ A && (B || C) no (A || B) && (A || C) ⇒ A || (B && C) DeMorgan’s theorem yes !(A || B) ⇒ (!A) && (!B) yes !(A && B) ⇒ (!A) || (!B) Other identities yes A && ((!A) || B) ⇒ A && B yes A || ((!A) && B) ⇒ A || B The consensus identities no (A && B) || ((!A) && C) || (B && C) ⇒ (A && B) || ((!A) && C)) yes (A && B) || (A && (!B) && C) ⇒ (A && B) || (A && C) yes (A && B) || ((!A) && C) ⇒ ((!A) || B) && (A || C) An expression containing a number of logical operators, each having operands whose evaluation involves relational or equality operators, can always be written in a number of different ways, for instance: 1 if ((X < 4) && !(Y || (Z == 1))) 2 /* ... */ 3 4 if ((Y != 0) && (Z != 0) && (X < 4)) 5 /* ... */ 6 7 if (!((X >= 4) || Y || (Z == 1))) 8 /* ... */ 9 10 if (X < 4) 11 if (!(Y || (Z == 1))) 12 /* ... */ An example of complexity in an English sentence might be “Suppose ﬁve days after the day before yesterday is Friday. What day of the week is tomorrow?” Whether the use of a less complex (i.e., having less cognitive load) expression has greater cost/beneﬁt than explicitly calling out the details of the calculation needs to be determined on a case-by-case basis. June 24, 2009 v 1.2
8. 1250 6.5.13 Logical AND operator categoriza- 0 A study by Feldman[423] found that the subjective difﬁculty of a concept (e.g., classifying colored polygons tion per- of various sizes) was directly proportional to its boolean complexity (i.e., the length of the shortest logically formance predicting equivalent propositional formula). Table 1248.2: Common token pairs involving &&, or || (as a percentage of all occurrences of each token). Based on the visible form of the .c ﬁles. Note: entries do not always sum to 100% because several token sequences that have very low percentages are not listed. Token Sequence % Occurrence % Occurrence of Token Sequence % Occurrence % Occurrence of of First Token Second Token of First Token Second Token identiﬁer && 0.4 48.5 && deﬁned 0.9 6.2 ) || 0.9 42.7 || ! 11.3 6.0 identiﬁer || 0.2 39.3 character-constant || 4.2 4.2 ) && 1.1 34.9 character-constant && 5.3 3.3 || deﬁned 4.8 21.0 && ( 28.7 0.9 integer-constant || 0.3 12.4 || ( 29.7 0.6 integer-constant && 0.4 11.5 && identiﬁer 53.9 0.5 && ! 13.5 11.3 || identiﬁer 51.8 0.3 Constraints && Each of the operands shall have scalar type. 1249 operand type Commentary The behavior is deﬁned in terms of an implicit comparison against zero, an operation which is only deﬁned for operands having a scalar type in C. C++ The operands are both implicitly converted to type bool (clause 4). 5.14p1 Boolean conversions (4.12) covers conversions for all of the scalar types and is equivalent to the C behavior. Other Languages Languages that support boolean types usually require that the operands to their logical-AND operator have boolean type. Coding Guidelines & binary 1235 operand type The discussion on the bitwise-AND operator is also applicable here, and the discussion on the comprehension if statement 1743 of the controlling expression in an if statement is applicable to both operands. controlling expression scalar type Table 1249.1: Occurrence of logical operators having particular operand types (as a percentage of all occurrences of each operator; an _ preﬁx indicates a literal operand). Based on the translated form of this book’s benchmark programs. Left Operand Operator Right Operand % Left Operand Operator Right Operand % int || int 87.7 _long || _long 2.2 int && int 73.9 int && ptr-to 2.2 other-types && other-types 12.8 int && char 1.8 other-types || other-types 8.4 int || _long 1.7 ptr-to && int 4.5 int && _int 1.3 char && int 2.3 ptr-to && ptr-to 1.1 Semantics v 1.2 June 24, 2009
9. 6.5.13 Logical AND operator 1250 1250 The && operator shall yield 1 if both of its operands compare unequal to 0; && operand com- pare against 0 Commentary The only relationship between the two operands is their appearance together in a logical-AND operation. There is no beneﬁt, from the implementations point of view, in performing the usual arithmetic conversions or the integer promotions on each operand. It is sometimes necessary to test a preliminary condition before the main condition can be tested. For instance, it may be necessary to check that a pointer value is not null before dereferencing it. The test could be performed using nested if statements, as in: 1 if (px != NULL) 2 if (px->m1 == 1) More complex conditions are likely to involve the creation of a warren of nested if statements. The original designers of the C language decided that it was worthwhile creating operators to provide a shorthand notation (i.e., the logical-AND and logical-OR operators). In the preceding case use of one of these operators allows both tests to be performed within a single conditional expression (e.g., if ((px != NULL) && (px->m1 == 1))). The other advantage of this operator, over nested if statements, is in the creation of expressions via the expansion of nested macro invocations. Generating nested if statements requires the use of braces to ensure that any following else arms are associated with the intended if arm. Generating these braces introduces additional complexities (at least another macro invocation in the source) that don’t occur when the && operator is used. C++ The result is true if both operands are true and false otherwise. 5.14p1 The difference in operand types is not applicable because C++ deﬁnes equality to return true or false. The difference in return value will not cause different behavior because false and true will be converted to 0 and 1 when required. Other Languages The mathematical use of this operator returns true if both operands are true. Languages that support a boolean data type usually follow this convention. Common Implementations 1111 logical As discussed elsewhere, loading a value into a register often sets conditional ﬂags as does a relational negation result is operation comparing two values. This means that in many cases machine code to compare against zero need 1210 relational operators not be generated, as in, the following condition: result value 1 if ((a == b) && (c < d)) which is likely to generate an instruction sequence of the form: compare a with b if not equal jump to else_or_endif compare c with d if greater than or equal to jump to else_or_endif code for if arm else_or_endif: rest of program June 24, 2009 v 1.2
10. 1253 6.5.13 Logical AND operator Coding Guidelines Should the operands always be explicitly compared against zero? When an operand is the result of a relational or equality operator, such a comparison is likely to look very unusual: 1 if (((a == b) == 0) && ((c < d) == 0)) It is assumed that developers think about the operands in terms of boolean roles and the result of both the relational and equality operators have a boolean role. In these cases another equality comparison is redundant. When an operand does not have a boolean role, an explicit comparison against zero might be appropriate ! 1113 (these issues are also discussed elsewhere). equivalent to selection 1739 statement syntax otherwise, it yields 0. 1251 Commentary That is, a value of zero having type int. && The result has type int. 1252 result type Commentary relational 1211 operators The rationale for this choice is the same as for relational operators. result type C++ The result is a bool. 5.14p2 The difference in result type will result in a difference of behavior if the result is the immediate operand of the sizeof operator. Such usage is rare. Other Languages In languages that support a boolean type, the result of logical operators usually has a boolean type. Common Implementations If the result is immediately cast to another type, an implementation may choose to arrange that other type as the result type; for instance, in: 1 float f(int ip) 2 { 3 return (ip > 0) && (ip < 10); 4 } an implementation may choose to return 0.0 and 1.0 as the result of the expression evaluation, saving a cast operation. Coding Guidelines relational 1211 operators The coding guideline issues are the same as those for the relational operators. result type && Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; 1253 evaluation order Commentary The left-to-right evaluation order of the && operator is required; it is what makes it possible for the left operand to verify a precondition for the evaluation of the right operand. There is no requirement that the evaluation of the right operand, if it occurs, take place immediately after the evaluation of the left operand. sequence 187.1 Coding Guidelines points This issue is covered by the guideline recommendation dealing with sequence points. all orderings give same value v 1.2 June 24, 2009
11. 6.5.13 Logical AND operator 1255 Example In the following: 1 #include 2 3 void f(void) 4 { 5 (printf("Hello ") && printf("World\n")) + printf("Goodbye\n"); 6 } possible output includes: Hello World Goodbye and Hello Goodbye World 1254 there is a sequence point after the evaluation of the ﬁrst operand. && sequence point Commentary 1250 && operand com- Unlike the nested if statement form, there is no guaranteed sequence after the evaluation of the second pare against 0 operand, if it occurs. C++ All side effects of the ﬁrst expression except for destruction of temporaries (12.2) happen before the second 5.14p2 expression is evaluated. 1025 function call The possible difference in behavior is the same as for the function-call operator. sequence point Coding Guidelines While the sequence point ensures that any side effects in the ﬁrst operand have completed, relying on this occurring creates a dependency within the expression that increases the effort needed to comprehend it. Some 941 object of the issues involving side effects in expressions are discussed elsewhere. modiﬁed once between sequence points Example 1 #include 2 3 extern int glob; 4 5 void f(void) 6 { 7 if (--glob && ++glob) 8 printf("The value of glob is neither 0 nor 1\n"); 9 } 1255 If the ﬁrst operand compares equal to 0, the second operand is not evaluated. && second operand Commentary An alternative way of looking at this operator is that x && y is equivalent to x ? (y?1:0) : 0. June 24, 2009 v 1.2
12. 1256 6.5.14 Logical OR operator Common Implementations This operand can be implemented, from the machine code generation point of view, as if a nested if construct had been written. Coding Guidelines Some coding guideline documents prohibit the second operand containing side effects. The rationale is that readers of the source may fail to notice that if the second operand is not evaluated any side effects it generates will not occur. The majority of C’s binary operators (32 out of 34) always evaluate both of their operands. Do developers make the incorrect assumption that the operands of all binary operators are always evaluated? Your author thinks not. Many developers are aware that in some cases the && operator is more efﬁcient than the & operator, because it only evaluates the second operand if the ﬁrst is not sufﬁcient to return a result. Although many developers may be aware of the conditional evaluation of the second operand, some will believe that both operands are evaluated. While a guideline recommendation against side effects in the second operand may have a beneﬁt for some developers, it potentially increases cost in that the alternative construct used may require more effort to comprehend (e.g., the alternative described before). Given that the alternative constructs that could be used are likely to require more effort to comprehend and the unknown percentage of developers making incorrect assumptions about the evaluation of the operands, no guideline recommendation is given. coverage testing Coverage testing There are software coverage testing requirements that are speciﬁc to logical operators. Branch condition decision testing involves the individual operands of logical operators. It requires that test cases be written to exercise all combinations of operands. In: 1 if (A || (B && C)) it is necessary to verify that all combinations of A, B, and C, are evaluated. In the case of the condition involving A, B, and C eight separate test cases are needed. For more complex conditions, the number of test cases rapidly becomes impractical. Modiﬁed condition decision testing requires that test cases be written to demonstrate that each operand can independently affect the output of the decision. For the if statement above, Table 1255.1 shows the possible conditions. Using modiﬁed condition, MC, coverage can signiﬁcantly reduce the number of test cases over branch condition, BC, coverage. Table 1255.1: Truth table showing how each operand of (A || (B && C)) can affect its result. Case 1 and 2 show that A affects the outcome; Case 3 shows that B affects the outcome; Case 3 and 4 shows that C affects the outcome. Case A B C Result 1 FALSE FALSE TRUE FALSE 2 TRUE FALSE TRUE TRUE 3 FALSE TRUE TRUE TRUE 4 FALSE TRUE FALSE FALSE The FAA requires[1204] that aviation software at Level A (the most critical, deﬁned as that which could prevent continued safe ﬂight and landing of the aircraft) have the level of coverage speciﬁed by MC/DC[103] (DC decision coverage). This requirement has been criticized as not having a worthwhile cost (money and time) and beneﬁt (the number of errors found) ratio. An empirical evaluation of the HETE–2 satellite software[379] looked at the faults found by various test methods and their costs. Logical operators can also appear within expressions that are not a condition context. The preceding coverage requirements also hold in these cases. Horgan and London[603] describe an Open Source tool that measures various dataﬂow coverage metrics for C source. 6.5.14 Logical OR operator v 1.2 June 24, 2009