3

フラグに列挙子の値を使用しています:

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;

MISRA-C:2004 によると、ビット単位の操作は符号付きの型では実行できません。残念ながら、私のコンパイラ IAR は、基になる列挙型としてsigned int (または short または char) を使用します。私が見つけることができる唯一のオプションは、signedness ("--enum-is-int") ではなく、サイズに関連しています。

4

2 に答える 2

2

IAR C/C++ Development Guide for ARMの 169 ページと 211 ページによるとenum、IAR 言語拡張 (-eコマンドライン オプション、または[プロジェクト] > [オプション] > [ C/C++ コンパイラ] > [言語] > IDE でIAR 拡張機能を許可します)。

特に、コンパイラが正しい型を選択するように、追加の "sentinel" 値を定義する必要があります。符号付きの型を優先し、可能な限り最小の整数型を使用するため、センチネルは、対応する符号なし整数型が記述できる最大の正の整数でなければなりません。例えば、

typedef enum {
    /* ... */
    enum_u8_sentinel = 255U
} enum_u8;

typedef enum {
    /* ... */
    enum_u16_sentinel = 65535U
} enum_u16;

typedef enum {
    /* ... */
    enum_u32_sentinel = 4294967295UL
} enum_u32;
于 2015-08-04T07:22:22.430 に答える
2

正の値は符号付きまたは符号なしの型と同じ表現を持つ必要があるため、列挙型に正の値のみを使用する場合、基になる型が符号付きか符号なしかは問題ではありません。標準は 6.2.6.2 Representation of types/Integer types §5 で述べています:符号ビットがゼロである符号付き整数型の有効な (非トラップ) オブジェクト表現は、対応する符号なし型の有効なオブジェクト表現であり、同じ値。

そのため、必要に応じて unsigned へのキャストを安全に行うことができます。とにかく、基になる型が char (または unsigned char) の場合、計算の前に (静かに) int に昇格できます。

IMHO、MISRA-C:2004 は、負の数の表現は実装定義であると標準が明示的に述べているため、ビット単位の操作は符号付きの型で実行されるべきではないと述べています。

符号付き整数型の場合、オブジェクト表現のビットは、値ビット、パディング ビット、符号ビットの 3 つのグループに分けられます。パディング ビットは必要ありません。正確に 1 つの符号ビットがあります... 符号ビットが 1 の場合、値は次のいずれかの方法で変更されます。

  • 符号ビット 0 の対応する値は否定されます (符号と大きさ)。
  • 符号ビットの値は -(2N) (2 の補数) です。
  • 符号ビットの値は -(2N - 1) (1 の補数) です。

  • これらのうちどれが適用されるかは実装定義です(私のものを強調してください)

TL/DR : 警告が表示されない場合 (ビット単位の|OR を使用しない場合) は、安全にキャストをまったく使用できません。符号なしの型に正の値をキャストする場合、表現は変更されないため、あなた (または企業の規則) が MISRA-C に従うことを選択した場合もキャストを実行できるため、符号なしの型に安全にキャストすることもできます。

于 2015-08-03T06:08:26.703 に答える