For VC++, here's the test about forward declaration and specifying the underlying type:
- The following code is compiled OK.
typedef int myint;
enum T ;
void foo(T * tp )
{
* tp = (T)0x12345678;
}
enum T : char
{
A
};
But I got the warning for /W4
(/W3
does not incur this warning)
warning C4480: nonstandard extension used: specifying underlying type for enum 'T'
- VC++ (Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86) looks buggy in the above case:
- when seeing enum T; VC assumes the enum type T uses default 4 bytes int as underlying type, so the generated assembly code is:
?foo@@YAXPAW4T@@@Z PROC ; foo
; File e:\work\c_cpp\cpp_snippet.cpp
; Line 13
push ebp
mov ebp, esp
; Line 14
mov eax, DWORD PTR _tp$[ebp]
mov DWORD PTR [eax], 305419896 ; 12345678H
; Line 15
pop ebp
ret 0
?foo@@YAXPAW4T@@@Z ENDP ; foo
The above assembly code is extracted from /Fatest.asm directly, not my personal guess.
Do you see the
mov DWORD PTR[eax], 305419896 ; 12345678H
line?
the following code snippet proves it:
int main(int argc, char *argv)
{
union {
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] );
return 0;
}
The result is:
0x78, 0x56, 0x34, 0x12
- After removing the forward declaration of enum T and move the definition of function foo after the enum T's definition: the result is OK:
The above key instruction becomes:
mov BYTE PTR [eax], 120 ; 00000078H
The final result is:
0x78, 0x1, 0x1, 0x1
Note the value is not being overwritten.
So using of the forward-declaration of enum in VC++ is considered harmful.
BTW, to not surprise, the syntax for declaration of the underlying type is same as its in C#. In pratice I found it's worth to save three bytes by specifying the underlying type as char when talking to the embedded system, which is memory limited.