web-dev-qa-db-ja.com

列挙型定義をunsignedintにキャストする

これによるとSO投稿:
Cでの列挙型のサイズはいくつですか?
列挙型にはsigned int型があります。

列挙型の定義をsigned intからunsigned intに変換したいと思います。

たとえば、私のプラットフォームでは、unsigned intは32ビット幅です。列挙型を作成したい:

typedef enum hardware_register_e
{
    REGISTER_STATUS_BIT = (1U << 31U)
} My_Register_Bits_t;

私のコンパイラは、上記の定義が範囲外であると文句を言っています(これはsigned int用です)。

unsigned intenum値を宣言するにはどうすればよいですか?

編集1:

  1. (コードは組み込みシステムに存在するため)64ビットに拡張しないことをお勧めします。
  2. スキルの制限により、このプロジェクトではC++は許可されていません。 :-(

編集2:

  • コンパイラは、ARM7用のIAR EmbeddedWorkbenchです。
7
Thomas Matthews

残念ながら、ISO C標準(c99 6.4.4.3)では、列挙定数のタイプはintであると規定されています。上記を例えばでコンパイルした場合gcc -W -std=c89 -pedantic、警告ISO C restricts enumerator values to range of ‘int’ [-pedantic]を発行します。一部の組み込みコンパイラは、コードをまったく受け入れない場合があります。

コンパイラの種類が多い場合は、次を使用して問題を回避できます。

typedef enum hardware_register_e
{
    REGISTER_STATUS_BIT = -2147483648   /* 1<<31, for 32-bit two's complement integers */
} hardware_register_t;

ただし、intがアーキテクチャ上の32ビット2の補数型である場合にのみ正しく機能します。これは、私が今まで使用または聞いたことのあるすべての32ビットおよび64ビットアーキテクチャにあります。

追加のために編集:ARM7は32ビット2の補数int型を使用するため、上記は正常に機能するはずです。実際の値は1<<31であることを説明するコメントを保持することをお勧めします。誰かがコードを移植したのか、別のコンパイラを使用したのかはわかりません。新しいコンパイラが警告を発した場合、同じ行のコメントで修正するのは簡単です。個人的には、コードを条件付きでラップします。

typedef enum hardware_register_e
{
#ifdef __ICCARM__
    REGISTER_STATUS_BIT = -2147483648   /* 1<<31, for 32-bit two's complement integers */
#else
    REGISTER_STATUS_BIT = 1 << 31
#endif
} hardware_register_t;
2
Nominal Animal

これによるとSO post:Cの列挙型のサイズはどれくらいですか?列挙型はint型に署名しています。

enumcanint型ですが、Cではintではありません。 gccに 1)enumタイプはデフォルトでunsigned intです。

enum定数はintですが、enumタイプは実装で定義されています。

あなたの場合、enum定数はintですが、intに収まらない値を指定しています。 Cがenumであると言っているので、Cにunsigned intint定数を含めることはできません。


1)gcc実装で定義された列挙型のドキュメント:「通常、列挙に負の値がない場合、型はunsigned intであり、そうでない場合はint」 http://gcc.gnu.org/onlinedocs/gcc/Structures -unions-enumerations-and-bit_002dfields-implementation.html

4
ouah

コンパイラに列挙型を符号なしにするオプションまたはプラグマがあるかどうかを確認してください。そうでない場合は、列挙型の代わりにプレーンなunsigned int(またはuint32_tなどの固定幅タイプ)を使用し、#definesを使用して定義する必要があります。それが取ることができる値。

1
Adam Rosenfield

列挙型のタイプを(少なくとも移植可能に)変更することはできません。標準では、列挙定数の型がintであることは明らかです。警告を取り除くには、キャストを使用できます。

typedef enum hardware_register_e
{
    REGISTER_STATUS_BIT = (int)(1U << 31U)
} My_Register_Bits_t;

可能な代替案

これをヘッダーに含める必要がない場合は、列挙定数の代わりに、必要なタイプのconstオブジェクトを使用できます。

const unsigned int REGISTER_STATUS_BIT = (1U << 31);

それ以外の場合は、次の定義を使用できます。

#define REGISTER_STATUS_BIT (1U << 31)
1
vitaut