Bitwise operation with an (signed) enumeration value

I use counter values ​​for flags:

typedef enum { a = 0x00, b = 0x01u, // the u has no influence, as expected c = 0x02u, // the u has no influence, as expected ... } enum_name; volatile unsigned char* reg = SomeAddress; *reg |= b; 

According to MISRA-C: 2004, bitwise operations must not be performed using a signed type. Unfortunately, the IAR IAR compiler uses a signed int (either short or char) as the main type of enumeration, and the only option I can find relates to size, not subscription ("--enum-is-int") .

+2
source share
2 answers

According to the IAR C / C ++ Development Guide for ARM , pages 169 and 211, you can determine the type of your enum if you enable IAR language extensions ( -e command-line option or Project> Options> C / C ++ Compiler> Language> Allow IAR Extensions in the IDE).

In particular, you must define an optional “sentinel” value to ensure that the compiler selects the correct type. He prefers signed types and uses the smallest possible integer type, so the sentinel must be the largest positive integer that can describe the corresponding unsigned integer type. For example,

 typedef enum { /* ... */ enum_u8_sentinel = 255U } enum_u8; typedef enum { /* ... */ enum_u16_sentinel = 65535U } enum_u16; typedef enum { /* ... */ enum_u32_sentinel = 4294967295UL } enum_u32; 
+2
source

It doesn’t matter if the base type is unsigned if you only use positive values ​​for your enumeration, because a positive value should have the same representation as a signed or unsigned type. The standard reads in 6.2.6.2 Representation of types / integer types §5: A real (nonlocal) representation of an object of signed integer type, where the sign bit is zero, is a real object representation of the corresponding unsigned type, and must represent the same value.

This way you can safely do unsigned broadcasts if you want. In any case, if the base type is char (or was an unsigned char), it can (silently) advance to int before any calculation.

IMHO, MISRA-C: 2004 says that battle operations should not be performed using a signed type, as the standard explicitly states that the representation of a negative number is defined by the implementation:

For signed integer types, the object representation bits must be divided into three groups: value bits, padding bits, and a sign bit. There should be no padding bits; there must be exactly one sign bit ... If the sign bit is one, the value must be changed in one of the following ways:

  • the corresponding value with the sign bit 0 is negated (sign and value);
  • the sign bit matters - (2N) (two additions);
  • the sign bit has a value of - (2N - 1) (one addition).

  • Which one relates to the implementation (emphasize mine)

TL / DR: If you do not have warnings (and you should not | bitwise or), you can safely not use any throw. If you assign a positive value to an unsigned type, the representative will not change, so you can also broadcast if you (or your corporate rules) decide to follow MISRA-C so that you can also safely use the unsigned type

+2
source

All Articles