嗨,我是 Visual Studio 新手,
我想使用 Windows 固有的
__readfsword()
和 __readgsword()
,但我只能对 x86 使用 __readfsword()
,对 64 位应用程序使用 __readgsword()
。我正在为 x86 和 64 位应用程序构建我的程序。
如果我将应用程序配置更改为 x86,则会抛出错误,指出
__readgsword()
是无效标识符,但它会识别 __readfsword()
并针对 64 位进行反向操作。
我想在不更改应用程序的情况下构建我的应用程序,但由于此错误,我每次更改配置时都必须更改代码。 Visual Studio 中是否有一个解决方案,我可以在不更改代码的情况下进行构建,并且它根据配置使用这些功能?
这个问题可以通过应用条件编译来解决。它是 C 和 C++ 的一项语言功能,允许根据编译时谓词包含或排除要编译的代码区域。
MSVC 提供了几个可用于派生谓词的预定义宏。有很多可供选择,挑战是选择最合适的。
这里的下意识反应是选择
_WIN32
与 _WIN64
。由于以下两个原因,这是不合适的:
_WIN32
和_WIN64
指的是不相关的概念:_WIN32
描述了正在使用的API(即Win32子系统的API),而_WIN64
是在针对64位时设置的-bit 版本的 Windows1.因此,要使用的正确预定义宏是那些描述目标架构的宏,通常具有
_M
前缀(“机器”的缩写),即 _M_X64
2 和 _M_IX86
。
涵盖了基本原则,以下是可能的实现:
#include <intrin.h>
unsigned short read_word(unsigned long offset) {
#if defined(_M_X64) && !defined(_M_ARM64EC)
return __readgsword(offset);
#elif defined(_M_IX86)
return __readfsword(offset);
#else
#error "Unsupported architecture"
#endif
}
这使编译器根据(编译器提供的)目标体系结构宏发出适当的代码。如果没有谓词匹配,则当编译器遇到
#error
指令时,编译将停止。
所有条件都在编译时严格评估,生成的目标代码是无分支的。
#error
情况也在编译时处理,通过继续或终止编译。
1 这样做的结果是,64 位应用程序项目通常同时定义了
_WIN32
和 _WIN64
,并且 #if defined(_WIN32)
并不意味着针对 32 位版本的 Windows。
2
_M_X64
也适用于 _M_ARM64EC
目标,其中“EC”是“仿真兼容”的缩写。我不知道内在函数是否是该模拟的一部分,因此条件排除 _M_ARM64EC
。