Bitwise operation with (signed) enum value

谁说我不能喝 提交于 2019-12-11 03:52:54

问题


I am using enumerator 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 shall not be done with a signed type. Unfortunately, My compiler IAR use signed int (or short or char) as underlying type of enums, and the only option I can find relates to the size, not the signedness ("--enum-is-int").


回答1:


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

In particular, you should define an extra "sentinel" value, to make sure the compiler chooses the correct type. It prefers signed types, and uses smallest possible integer type, so the sentinel should be the largest positive integer the corresponding unsigned integer type can describe. 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:


It does not matter whether the underlying type is signed of unsigned, provided you only use positive values for your enum, because a positive value should have same representation as a signed or unsigned type. Standard says at 6.2.6.2 Representation of types/Integer types §5 : A valid (non-trap) object representation of a signed integer type where the sign bit is zero is a valid object representation of the corresponding unsigned type, and shall represent the same value.

So you can safely do the cast to unsigned if you want to. Anyway, if the underlying type is char (or was unsigned char), it can be (silently) promoted to int before any computation.

IMHO, MISRA-C:2004 says that bitwize operations shall not be done with a signed type, because the standard explicitely says that the representation of a negative number is implementation defined :

For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. There need not be any padding bits; there shall be exactly one sign bit... If the sign bit is one, the value shall be modified in one of the following ways:

  • the corresponding value with sign bit 0 is negated (sign and magnitude);
  • the sign bit has the value -(2N) (two’s complement);
  • the sign bit has the value -(2N - 1) (ones’ complement).

  • Which of these applies is implementation-defined (emphasize mine)

TL/DR : If you have no warning (and you should not for a | bitwise or) you can safely use no cast at all. If you cast to the unsigned type a positive value the representatin is unchanged so you can also do the cast if you (or your corporate rules) choose to follow MISRA-C, so you can also safely cast to an unsigned type



来源:https://stackoverflow.com/questions/31780026/bitwise-operation-with-signed-enum-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!