LPNMITEMACTIVATE 和代码分析 (C26462)

LPNMITEMACTIVATE and code analysis (C26462)

为什么在 LPNMITEMACTIVATE 的 SDK 源代码中用 左边 的星号定义?

typedef struct tagNMITEMACTIVATE
{
    NMHDR   hdr;
    int     iItem;
    int     iSubItem;
    UINT    uNewState;
    UINT    uOldState;
    UINT    uChanged;
    POINT   ptAction;
    LPARAM  lParam;
    UINT    uKeyFlags;
} NMITEMACTIVATE, *LPNMITEMACTIVATE;

我总是习惯指针在右边。无论哪种方式,代码如下:

const LPNMITEMACTIVATE pNMItem = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);

仍会标记 const (C26462) 警告:

如果我将代码更改为:

const NMITEMACTIVATE* pNMItem = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);

警告将消失。

这是标准的C/C++

就像这个(不可运行的)代码片段:

typedef int *LPINT;
//  typedef int* LPINT;  // you could write this, it's exactly the
                         // the same as above

int main()
{
  LPINT pint;
  int* pint2;

  *pint = *pint2;
}

pintpint2都是指向int的指针。顺便说一句,这是在 typedef 后面隐藏了一个指针类型,这是一个坏主意(但在旧的 MS 时代被认为是一个好主意),但是很多 Microsoft headers 仍然有这些 typedef sometype *LPsometype; typedefs兼容性原因。

另一个更接近您所指的 MS header 的示例:

这个:

typedef struct tagNMITEMACTIVATE
{
  int   hdr;
  int     iItem;
} NMITEMACTIVATE, *LPNMITEMACTIVATE;

相当于:

typedef struct tagNMITEMACTIVATE
{
  int   hdr;
  int     iItem;
} NMITEMACTIVATE;

typedef struct tagNMITEMACTIVATE *LPNMITEMACTIVATE;

因为指针 const 可以应用于指针指向的类型:

const NMITEMACTIVATE* p;

NMITEMACTIVATE const* p;

或者可以应用于指针变量本身:

NMITEMACTIVATE* const p;

现在如果你有 typedef:

typedef NMITEMACTIVATE *PNMITEMACTIVATE;

const 不适用于所指向的类型。无论哪种方式,指针本身都是常量:

const PNMITEMACTIVATE p;
PNMITEMACTIVATE const p;

为避免这种混淆,最好不要使用原始指针类型定义(也不要定义它们)。

我用 Visual Studio 2022 试过了,首先,默认情况下没有启用警告 C26462。也许您使用的是较早的版本,或者我的安装有些奇怪。

手动启用警告后,我可以通过多次分配 pNMItem 使警告消失:

LPNMITEMACTIVATE pNMItem = nullptr;
pNMItem = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);

这有什么用?

或者可以按照其他答案中的建议进行修复。但是您可能还有其他问题,因为 pNMHDR 可能被声明为 LPNMHDR,因此您必须重写更多行:

NMHDR hdr = { 0 };
const NMHDR* pNMHDR = reinterpret_cast<NMHDR*>(&hdr);
const NMITEMACTIVATE* pNMItem = reinterpret_cast<const NMITEMACTIVATE*>(pNMHDR);

这可能会浪费大量时间。请注意,如果您正在编写应该在任何系统上 运行 的代码,则建议额外遵守。但是 MFC 与 Windows 相关联,因此这并不是真正的问题。 MFC 和 Windows 仍在使用 16 位 Windows 遗留下来的“长指针”废话,它们本身不兼容,因此请考虑关闭其中一些警告。