Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: An attempt to add few details about why the first paragraph mentions to use operators & ^ | (also MISRA-C:2004 Rule 12.7) only on unsigned operands. That all bitwise operations on signed integers are implementation-defined in C90.

Bitwise operators include the complement operator ~, bitwise shift operators >> and <<, bitwise AND operator &, bitwise exclusive OR operator ^, and bitwise inclusive OR operator | and compound assignment operators >>=, <<=, &=, ^= and |=. Bitwise operators should be used only with unsigned integer operands, as the results of some bitwise operations on signed integers are implementation-defined (Annex G.3.5 [ISO/IEC 9899:1990]).

The C90 Standard, 6.3, paragraph 4 [ISO/IEC 9899:1990], states:

Some operators (the unary operator ~ , and the binary operators <<, >>, &, ^, and |, collectively described as bitwise operators) shall have operands that have integral type. These operators return values that depend on the internal representations of integers, and thus have implementation-defined aspects for signed types.

Further,  bitwise shift operator << for signed type is not defined in C90 subclause 6.3.7 [ISO/IEC 9899:1990].

Implementation details

The Microsoft C compiler documentation says that:

Bitwise operations on signed integers work the same as bitwise operations on unsigned integers.

On-line GCC documentation about the implementation of some bitwise operations on signed integers says:

Bitwise operators act on the representation of the value including both the sign and value bits, where the sign bit is considered immediately above the highest-value value bit.

Noncompliant Code Example (Right Shift)

...

Also, consider using the sprintf_s() function, defined in ISO/IEC TR 24731-1, instead of snprintf() to provide some additional checks. (See STR07-C. Use the bounds-checking interfaces for string manipulation.)

Noncompliant Code Example (enum)

In this noncompliant code example, initializer expressions for all enumeration constants in enum attrib_mask are unsigned integers. However, the C Standard says (section 6.1.3.3 [ISO/IEC 9899:1990]) that enumeration constants have type int. The bitwise OR is applied to signed integers which is implementation-defined behavior.

Code Block
bgColor#FFcccc
langc
enum attrib_mask
{
  POINT_BIT = 0x02U,
  LINE_BIT  = 0x04U
};
unsigned int mask = (POINT_BIT | LINE_BIT);

Compliant Solution (enum)

One solution is to cast the enumeration constants to an unsigned type to eliminate any possible implementation-defined behavior. The initializer expressions and enumeration constants have type int:

Code Block
bgColor#ccccff
langc
enum attrib_mask
{
  POINT_BIT = (1 << 1),
  LINE_BIT  = (1 << 2)
};
unsigned int mask = ((unsigned int)POINT_BIT | (unsigned int)LINE_BIT);

Exceptions

INT13-EX1: When used as bit flags, it is acceptable to use preprocessor macros as arguments to the & and | operators even if the value is not explicitly declared as unsigned.

...