You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 21 Next »

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.

Bitmapped types may be defined to further separate bit collections from numeric types. This may make it easier to verify that bit manipulations are only performed on variables that represent bitmaps.

typedef uint32_t bitmap32_t;
bitmap32_t bm32 = 0x000007f3;

x = (x << 2) | 3; /* shifts in two 1-bits from the right */

The typedef name uintN_t designates an unsigned integer type with width N. Therefore, uint32_t denotes an unsigned integer type with a width of exactly 32 bits. Bitmaps are normally assigned an unsigned type.

Non-Compliant Code Example 1

In this non-compliant code example, both bit manipulation and arithmetic manipulation are 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 optimize a division by four operation by shifting right by two.

int x = -50;
x >>= 2;

Although this code is likely to perform the division by 4 correctly, 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. In the event of a logical shift, if the integer is represented in either one's complement or two's complement form, the most significant bit (which controls the sign in a different way for both representations) will be set to zero. This will cause a once negative number to become a possibly very large positive number.

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).

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 programmer's expectations.

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:TC2]] Section 6.2.6.2, "Integer types"

[[Steele 77]]

  • No labels