5

タイプパンされた逆参照

私は列挙型を持っています

enum AgentStatus { kSTOPPED = 0, kRUNNING, kIDLE, kNAGENTSTATUS };

多くのオーバーロードされたバリアントを持つ外部ライブラリの関数に渡す必要があります。2番目の引数に渡したい:

DimService::DimService(const char*, int&);
DimService::DimService(const char*, char*);
...

enum 変数を (int&) にキャストすると、悪名高い警告が表示されます。

warning: dereferencing type-punned pointer will break strict-aliasing rules

(int) にキャストすると、これが得られます

invalid conversion from ‘int’ to ‘char*’
error:   initializing argument 2 of ‘DimService::DimService(const char*, char*)’

正しい方法は何ですか?

4

2 に答える 2

8

インライン キャストで問題が発生した場合は、別の行として分割すると役立つ場合があります。

const AgentStatus enumValue = kRUNNING;
...
int intValue = static_cast<int>(enumValue);
DimService("works now", intValue);
于 2013-02-15T14:58:06.920 に答える
6

ビルからの回答は、技術的には正解です。

1) 別のアプローチ

型の列挙性を取り除く必要がある場合にこれを行う別の方法は、型を int 自体にすることです。

typedef int MyEnum;
enum
{
    CONST1 = 0,
    etc...
};

そして、それを通常のように使用してください。コンパイラは値の不適切な割り当てをキャッチしませんが、すべての宣言を MyEnum 型としてタグ付けできるため、何が起こっているかを追跡するのに十分単純であり、int と表示されている場所ならどこでも変数を渡すことができます。

2) 危険なアプローチ

これは絶対にしないでください!

EnumType v = EnumValue_...

MyFunction( *((int*)&v) );

またはこれ...

#define MAKE_INT_REF(v) *((int*)&(v))

MyFunction( MAKE_INT_REF(v) );

その理由は、コンパイラが列挙型に使用する型を自動的に選択できるためです。int を選択する場合もあれば、char を選択する場合もあります。コンパイラやプラットフォームが異なると確信が持てません。そのため、列挙型をキャストしようとすると、移植性のないコードと非常に危険なコードが作成されます。そのようなキャストに書き戻すと、他の値が上書きされる可能性があるためです。

于 2013-02-15T15:08:34.810 に答える