代码之家  ›  专栏  ›  技术社区  ›  Andrew Truckle

警告C6273:当需要整数时,非整数作为_Param_(2)传递

  •  0
  • Andrew Truckle  · 技术社区  · 8 年前

    我有这个方法:

    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); \
            } \
        }
    

    以上是提供给我的第三方宏,它与应用程序重启程序可执行文件一起工作。原作者不再可用。

    应用程序构建并正常运行。但我得到了一个代码分析错误:

    警告C6273:作为传递的非整数 (2) 当整数为 要求 “ATL::CStringT>

    ::格式“实际类型:'struct HWND__*”:如果正在传递指针值,则应使用%p。

    的确 _hWndMain 是典型的 HWND 但我不能用 %p 作为格式代码。如果我这样做,那么应用程序重启程序将失败,并告诉我它希望这个参数是数值。

    如您所见,我恢复使用%ld,我认为这是正确的。

    通过更改我的代码可以抑制此警告吗?还是这只是我必须忍受的假阳性?

    1 回复  |  直到 8 年前
        1
  •  2
  •   Community paulsm4    7 年前

    它是 假阳性;警告是正确的,并捕获了一个错误。 %ld 不正确,因为指针不是整数。语言规范明确了这一事实,因此 %ld 是错误的,因为它指示函数将指针值解释为长整数。其中一种可能出错的方法是针对64位处理器,其中指针是64位宽,但整数(包括 long s、 仅32比特宽)。 %ld 将切掉上面的部分。

    具有 CString<T>::Format ,你必须按照与 printf ,这就是为什么警告告诉您需要使用 %p 以传递指针值。为什么 HWND 被视为指针是因为这是在Windows标头中定义类型的方式。从技术上讲,它不是指针,只是一个不透明的值,但指针语义通常是合适的,可以避免错误。

    你用 %p 不是选项,因为您会收到参数不是数字的错误。我猜那是因为 %p 导致值以某种格式打印,该格式: CString<T>::总体安排 认为适合指针值,可能是十六进制值,甚至可能是 0x 前缀,但传递该格式化字符串的函数不需要它。

    因此,您需要显式地解释 HWND 值作为数字值,然后与一起使用 %ld .这不仅会使警告保持沉默,而且会给出正确的语义。但是您需要仔细选择要使用哪种类型来表示它。你的第一直觉可能是 size_t ,但该标准不能保证与指针具有相同的宽度。它将在Windows 32位和64位上“工作”,但在技术上无效。相反,为了安全起见 intptr_t uintptr_t ,这取决于您想要地址的有符号表示还是无符号表示。对于格式字符串,使用 %Id , %Ix %IX .从当前代码的外观来看,您可能希望 %身份证 。您可能还需要明确指出字段的大小,具体取决于消费者期望的格式。

    strCmdLine.Format(_T("%Id %ld \"%s\""),
                      reinterpret_cast<intptr_t>(_hWndMain),
                      _dwProcessID,
                      static_cast<LPCTSTR>(strAppFilespec));
    

    您需要确保您已包括在内 <inttypes.h> .

    (注意 %I 格式说明符是微软的发明,因此不可移植。在其他编译器上,您可以 use the standard macros from inttypes.h .我认为微软的实现中不存在这些,尽管我面前没有编译器。也许你可以证明我错了?)