问题描述
docs for ShellExecute
状态(斜体强调我的):
返回值
类型:HINSTANCE
如果函数成功,则返回一个大于 32 的值。如果函数失败,则返回一个错误值,指出失败的原因。返回值被强制转换为 HINSTANCE,以便与 16 位 Windows 应用程序向后兼容。然而,这不是真正的 HINSTANCE。 它只能转换为 int 并与 32 或以下错误代码进行比较。
但是,像这样服从他们:
if ((int)ShellExecuteW(...) <= 32) ...
使用 MSVC 2019(32 位和 64 位)编译时产生警告:
warning C4311: 'type cast': pointer truncation from 'HINSTANCE' to 'int'
warning C4302: 'type cast': truncation from 'HINSTANCE' to 'int'
使用 reinterpret_cast<int>
会产生类似的结果。
我可以取消该行的警告:
#pragma warning(suppress: 4311 4302)
if ((int)ShellExecuteW(...) <= 32) ...
但我通常不喜欢这样做,除非没有其他选择。因此,我的问题是:还有其他选择吗?是否有一些 C++ 语法可以让我尊重 API 文档而不产生警告?
解决方法
HINSTANCE
是指针类型。编译器警告您指针的大小大于 int
的大小,因此在将 HINSTANCE
转换为 int
期间,位将被截断。当您为 64 位编译时会发生这种情况,其中指针为 8 个字节,int
为 4 个字节。
在这种特殊情况下,这种截断很好,因为这些值永远不会超过 int
可以容纳的值。但是,如果您真的想避免这些警告,那么只需使用 intptr_t
或 INT_PTR
或任何其他类似的指针大小的整数类型,例如:
if (reinterpret_cast<intptr_t>(ShellExecuteW(...)) <= 32) {
...
}
否则,根本不要使用ShellExecute()
,而是使用ShellExecuteEx()
。它返回一个 BOOL
表示成功/失败,并使用 GetLastError()
报告失败时的标准 Win32 错误代码(ShellExecute()
返回的大多数错误代码不是标准的 Win32 错误代码),例如:
SHELLEXECUTEINFOW info = {...};
if (!ShellExecuteExW(&info)) {
DWORD error = GetLastError();
...
}