警告 C6273:当需要整数时,非整数作为 _Param_(2) 传递
warning C6273: Non-integer passed as _Param_(2) when an integer is required
我有这个方法:
void CMeetingScheduleAssistantDlg::RestartProgram()
{
RESTART_THIS_MFC_APP;
}
它调用定义的宏:
#define RESTART_THIS_MFC_APP \
{ \
HWND _hWndMain = AfxGetApp()->m_pMainWnd->GetSafeHwnd(); \
DWORD _dwProcessID = (DWORD)_getpid(); \
TCHAR _cFilespec[_MAX_PATH + 1]; \
if (::GetModuleFileName(AfxGetInstanceHandle(), _cFilespec,_MAX_PATH) == 0) \
AfxMessageBox(_T("ERROR: Could not obtain full filespec of this application to restart it."), MB_OK|MB_ICONSTOP); \
else \
{ \
CString strAppFilespec(_cFilespec); \
; \
LPTSTR lpszFilename = ::PathFindFileName(_cFilespec); \
_tcscpy_s(lpszFilename,_MAX_PATH - (lpszFilename - _cFilespec),_T("AppRestarter.exe") ); \
; \
CString strAppRestarterFilespec(_cFilespec); \
; \
CString strCmdLine ; \
strCmdLine.Format(_T("%ld %ld \"%s\""),_hWndMain,_dwProcessID,(LPCTSTR)strAppFilespec); \
; \
HINSTANCE hProcess = ::ShellExecute(NULL,_T("open"),(LPCTSTR)strAppRestarterFilespec, \
(LPCTSTR)strCmdLine,_T(".\"), SW_HIDE); \
if ( (DWORD)(DWORD_PTR)hProcess <= 32) \
AfxMessageBox(_T("ERROR: Could not run application restarter."), MB_OK|MB_ICONSTOP); \
} \
}
以上是提供给我的第三方宏,可与应用程序重启器可执行文件一起使用。原作者不在了
应用程序已构建并正常运行。但是我收到代码分析错误:
warning C6273: Non-integer passed as Param(2) when an integer is
required in call to
'ATL::CStringT >
::Format' Actual type: 'struct HWND__ *': if a pointer value is being passed, %p should be used.
_hWndMain
确实是 HWND
类型,但我不能使用 %p
作为格式代码。如果我这样做,那么应用程序重启器会失败并告诉我它希望此参数为数字。
正如您所见,我恢复使用 %ld,我认为这是正确的。
是否可以通过更改我的代码来抑制此警告?或者这只是我必须忍受的误报?
不是误报;警告是正确的,并发现了一个错误。 %ld
不对,因为指针不是整数。语言规范在这个事实上很清楚,所以 %ld
是错误的,因为它指示函数将指针值解释为长整数。这可能出错的多种方式之一是针对 64 位处理器,其中指针是 64 位宽但整数(包括 long
s,只有 32 位宽)。 %ld
将砍掉高位。
使用 CString<T>::Format
时,您必须按照与 printf
相同的规则进行游戏,这就是警告告诉您需要使用 %p
来传递指针值的原因。 HWND
被认为是指针的原因是因为这是在 Windows headers 中定义类型的方式。它在技术上不是指针,只是一个不透明的值,但指针语义通常是合适的并且避免了错误。
你说使用 %p
不是一个选项,因为你得到一个参数不是数字的错误。我猜那是因为 %p
导致值以 CString<T>::Format
认为适合指针值的某种格式打印,可能是十六进制的,甚至可能是 0x
前缀,但是您将该格式化字符串传递给的函数并不期望这样。
因此,在与 %ld
一起使用之前,您需要明确地将 HWND
值解释为数值。这不仅会消除警告,还会为您提供正确的语义。但是您需要仔细选择您将使用哪种类型来表示它。您的第一直觉可能是 size_t
,但标准并不能保证这与指针具有相同的宽度。它将在 Windows 32 位和 64 位上 "work",但在技术上无效。相反,为了安全起见,更喜欢 intptr_t
或 uintptr_t
,具体取决于您想要地址的有符号表示还是无符号表示。对于格式字符串,使用 %Id
、%Ix
或 %IX
。从当前代码的外观来看,您可能需要 %Id
。您可能还需要明确指出字段的大小,具体取决于消费者期望的格式。
strCmdLine.Format(_T("%Id %ld \"%s\""),
reinterpret_cast<intptr_t>(_hWndMain),
_dwProcessID,
static_cast<LPCTSTR>(strAppFilespec));
您需要确保包含 <inttypes.h>
。
(请注意,%I
格式说明符是 Microsoft 的发明,因此不可移植。在其他编译器上,您会 use the standard macros from inttypes.h
。我认为 Microsoft 的实现中不存在这些,尽管我我面前没有编译器。也许你能证明我是错的?)
我有这个方法:
void CMeetingScheduleAssistantDlg::RestartProgram()
{
RESTART_THIS_MFC_APP;
}
它调用定义的宏:
#define RESTART_THIS_MFC_APP \
{ \
HWND _hWndMain = AfxGetApp()->m_pMainWnd->GetSafeHwnd(); \
DWORD _dwProcessID = (DWORD)_getpid(); \
TCHAR _cFilespec[_MAX_PATH + 1]; \
if (::GetModuleFileName(AfxGetInstanceHandle(), _cFilespec,_MAX_PATH) == 0) \
AfxMessageBox(_T("ERROR: Could not obtain full filespec of this application to restart it."), MB_OK|MB_ICONSTOP); \
else \
{ \
CString strAppFilespec(_cFilespec); \
; \
LPTSTR lpszFilename = ::PathFindFileName(_cFilespec); \
_tcscpy_s(lpszFilename,_MAX_PATH - (lpszFilename - _cFilespec),_T("AppRestarter.exe") ); \
; \
CString strAppRestarterFilespec(_cFilespec); \
; \
CString strCmdLine ; \
strCmdLine.Format(_T("%ld %ld \"%s\""),_hWndMain,_dwProcessID,(LPCTSTR)strAppFilespec); \
; \
HINSTANCE hProcess = ::ShellExecute(NULL,_T("open"),(LPCTSTR)strAppRestarterFilespec, \
(LPCTSTR)strCmdLine,_T(".\"), SW_HIDE); \
if ( (DWORD)(DWORD_PTR)hProcess <= 32) \
AfxMessageBox(_T("ERROR: Could not run application restarter."), MB_OK|MB_ICONSTOP); \
} \
}
以上是提供给我的第三方宏,可与应用程序重启器可执行文件一起使用。原作者不在了
应用程序已构建并正常运行。但是我收到代码分析错误:
warning C6273: Non-integer passed as Param(2) when an integer is required in call to 'ATL::CStringT >
::Format' Actual type: 'struct HWND__ *': if a pointer value is being passed, %p should be used.
_hWndMain
确实是 HWND
类型,但我不能使用 %p
作为格式代码。如果我这样做,那么应用程序重启器会失败并告诉我它希望此参数为数字。
正如您所见,我恢复使用 %ld,我认为这是正确的。
是否可以通过更改我的代码来抑制此警告?或者这只是我必须忍受的误报?
不是误报;警告是正确的,并发现了一个错误。 %ld
不对,因为指针不是整数。语言规范在这个事实上很清楚,所以 %ld
是错误的,因为它指示函数将指针值解释为长整数。这可能出错的多种方式之一是针对 64 位处理器,其中指针是 64 位宽但整数(包括 long
s,只有 32 位宽)。 %ld
将砍掉高位。
使用 CString<T>::Format
时,您必须按照与 printf
相同的规则进行游戏,这就是警告告诉您需要使用 %p
来传递指针值的原因。 HWND
被认为是指针的原因是因为这是在 Windows headers 中定义类型的方式。它在技术上不是指针,只是一个不透明的值,但指针语义通常是合适的并且避免了错误。
你说使用 %p
不是一个选项,因为你得到一个参数不是数字的错误。我猜那是因为 %p
导致值以 CString<T>::Format
认为适合指针值的某种格式打印,可能是十六进制的,甚至可能是 0x
前缀,但是您将该格式化字符串传递给的函数并不期望这样。
因此,在与 %ld
一起使用之前,您需要明确地将 HWND
值解释为数值。这不仅会消除警告,还会为您提供正确的语义。但是您需要仔细选择您将使用哪种类型来表示它。您的第一直觉可能是 size_t
,但标准并不能保证这与指针具有相同的宽度。它将在 Windows 32 位和 64 位上 "work",但在技术上无效。相反,为了安全起见,更喜欢 intptr_t
或 uintptr_t
,具体取决于您想要地址的有符号表示还是无符号表示。对于格式字符串,使用 %Id
、%Ix
或 %IX
。从当前代码的外观来看,您可能需要 %Id
。您可能还需要明确指出字段的大小,具体取决于消费者期望的格式。
strCmdLine.Format(_T("%Id %ld \"%s\""),
reinterpret_cast<intptr_t>(_hWndMain),
_dwProcessID,
static_cast<LPCTSTR>(strAppFilespec));
您需要确保包含 <inttypes.h>
。
(请注意,%I
格式说明符是 Microsoft 的发明,因此不可移植。在其他编译器上,您会 use the standard macros from inttypes.h
。我认为 Microsoft 的实现中不存在这些,尽管我我面前没有编译器。也许你能证明我是错的?)