Avoid performing bit manipulation and arithmetic operations on the same variable. Though such operations are valid and will compile, they can reduce code readability. Declaring a variable as containing a numeric value or a bitmap makes the programmer's intentions clearer and can lead to better code maintainability.
Non-Compliant Code Example 1
In this non-compliant code example, both bit manipulation and arithmetic manipulation is performed on the integer type x
. The result is a (prematurely) optimized statement that assigns 5x + 1
to x
for implementations where integers are represented as two's complement values.
int x = 50; x += (x << 2) + 1;
Although this is a legal manipulation, the result of the shift depends on the underlying representation of the integer type, and is consequently implementation-defined. Additionally, the readability of the code is impaired.
Compliant Solution 1
In this compliant solution, the assignment statement is modified to reflect the arithmetic nature of x
resulting in a clearer indication of the programmer's intentions.
int x = 50; x = 5 * x + 1;
A reviewer may now recognize that the operation should be checked for integer overflow. This might not have been apparent in the original, non-compliant code example.
Non-Compliant Code Example 2
In this non-compliant code example, the programmer attempts to (prematurely) optimize dividing{{x}} by 4.
int x = -50; x >>= 2;
Although this code is likely to perform a division by 4, it is not guaranteed to. If x
has a signed type and a negative value, the operation is implementation-defined and could be implemented as either an arithmetic shift or a logical shift.
For example, if the internal representation of x
is 0xFFFF FFCE
(two's-complement), an arithmetic shift results in 0xFFFF FFF3
(-13 in two's-complement), while a logical shift results in 0x3FFF FFF3
(1 073 741 811 in two's-complement).
The result of the shift also depends on the underlying representation of the integer type.
Compliant Solution 2
In this compliant solution, the shift is replaced by a division operation so that the intention is clear.
int x = -50; x /= 4;
The resulting value is now more likely to be consistent with the programmers expectations.
Compliant Practice
To further separate bit collections and numeric types, it might be prudent to define a bitmapped type. A programmer can then run automated tools over the code in question to verify that only bit manipulations are performed on variables of this type.
typedef int bitmap; bitmap x = 0x7f3; x = (x << 2) | 3; /* shifts in two 1-bits from the right */
Risk Assessment
By complicating information regarding how a variable is used in code, it is difficult to determine which checks must be performed to ensure data validity. Explicitly stating how a variable is used determines which checks to perform.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
INT14-A |
2 (medium) |
1 (unlikely) |
2 (medium) |
P4 |
L3 |
References
[[ISO/IEC 9899-1999]] Section 6.2.6.2, "Integer types"
Steele, G. L. 1977. Arithmetic shifting considered harmful. SIGPLAN Not. 12, 11 (Nov. 1977), 61-69.