对于VC++,这里是关于前向声明和指定底层类型的测试:
- 以下代码编译OK。
typedef int myint;
枚举 T ;
无效 foo(T * tp )
{
* tp = (T)0x12345678;
}
枚举 T:字符
{
一种
};
但是我收到了警告/W4
(/W3
不会引起此警告)
警告 C4480:使用了非标准扩展:为枚举“T”指定基础类型
- VC++(Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86)在上述情况下看起来有问题:
- 当看到枚举 T 时;VC 假设枚举类型 T 使用默认的 4 字节 int 作为底层类型,因此生成的汇编代码为:
?foo@@YAXPAW4T@@@Z PROC ; 富
; 文件 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号线
流行音乐
0
?foo@@YAXPAW4T@@@Z ENDP ; 富
上面的汇编代码是直接从/Fatest.asm中提取出来的,不是我个人的猜测。
你看到
mov DWORD PTR[eax], 305419896 ; 12345678H
线?
下面的代码片段证明了这一点:
int main(int argc, char *argv)
{
联合{
字符 ca[4];
吨;
}一种;
a.ca[0] = a.ca[1] = a.[ca[2] = a.ca[3] = 1;
富(&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++ 中使用 enum 的前向声明被认为是有害的。
顺便说一句,毫不奇怪,底层类型的声明语法与 C# 中的相同。在实践中,我发现在与内存有限的嵌入式系统通信时,通过将底层类型指定为 char 来节省三个字节是值得的。