VCの場合、前方宣言と基になる型の指定に関するテストは次のとおりです。
- 次のコードは問題なくコンパイルされています。
typedef int myint;
列挙型T;
void foo(T * tp)
{
* tp =(T)0x12345678;
}
列挙型T:char
{
あ
};
しかし/ W4の警告を受けました(/ W3はこの警告を受けません)
警告C4480:非標準の拡張機能が使用されています:enum 'T'の基になる型を指定しています
上記の場合、VC(Microsoft(R)32ビットC / C ++最適化コンパイラバージョン15.00.30729.01 for 80x86)はバグがあるように見えます。
- 列挙型Tを参照するとき; VCは、列挙型Tがデフォルトの4バイトintを基本型として使用することを前提としているため、生成されるアセンブリコードは次のとおりです。
?foo @@ YAXPAW4T @@@ Z PROC; foo
; ファイルe:\ work \ c_cpp \ cpp_snippet.cpp
; 行13
ebpをプッシュ
mov ebp、esp
; 行14
mov eax、DWORD PTR _tp $ [ebp]
mov DWORD PTR [eax]、305419896、12345678H
; 行15
ポップebp
ret 0
?foo @@ YAXPAW4T @@@ Z ENDP; foo
上記のアセンブリコードは/Fatest.asmから直接抽出されたものであり、個人的な推測ではありません。mov DWORD PTR [eax]、305419896が表示されますか。12345678Hライン?
次のコードスニペットはそれを証明します。
int main(int argc、char * argv)
{
ユニオン{
char ca [4];
T t;
} a;
a.ca [0] = a.ca [1] = a。[ca [2] = a.ca [3] = 1;
foo(&a.t);
printf( "%#x、%#x、%#x、%#x \ n"、a.ca [0]、a.ca [1]、a.ca [2]、a.ca [3]) ;
0を返します。
}
結果は0x78、0x56、0x34、0x12です。
- enum Tの前方宣言を削除し、関数fooの定義をenum Tの定義の後に移動します。結果はOKです。
上記の重要な指示は次のようになります。
mov BYTE PTR [eax]、120; 00000078H
最終結果は0x78、0x1、0x1、0x1です。
値が上書きされていないことに注意してください
したがって、VCでの列挙型の前方宣言の使用は有害であると見なされます。
ちなみに、当然のことながら、基になる型の宣言の構文はC#の構文と同じです。実際には、組み込みシステムと通信するときに、基になる型をcharとして指定することで3バイトを節約する価値があることがわかりました。これは、メモリが限られているためです。