理解:从long_ptr转换为bool可能导致数据丢失

时间:2016-05-26 05:52:05

标签: winapi visual-c++ casting

我刚开始学习C ++并学习winapi,我正在做Forgers Win32 API教程。

这是我的代码:

//MyControl.h
#pragma once

#include <windows.h>
#include "resource.h"

BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
BOOL BrushExists(HBRUSH hBrush);
-------------------------------------------------------
//MyControl.cpp
#include "MyControl.h"

HBRUSH g_hbrBackground = NULL;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    return (int)DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)DlgProc);
}

BOOL BrushExists(HBRUSH hBrush) // I added this to better understand what is happening
{
    if (hBrush)
        return TRUE;
    else
        return FALSE;
}

BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
    case WM_INITDIALOG:
    {
        g_hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
//... Other code skipped copy pasting ...
    }
        break;
    case WM_COMMAND:
//... Other code skipped copy pasting ...
        break;
    case WM_CTLCOLORDLG:
        return (LONG_PTR)g_hbrBackground; // Where casting happens
//      return BrushExists(g_hbrBackground); // Tried this to understand things
        break;
    case WM_CTLCOLORSTATIC:
    {
        HDC hdcStatic = (HDC)wParam;
        SetTextColor(hdcStatic, RGB(255, 255, 255));
        SetBkMode(hdcStatic, TRANSPARENT);
        return (LONG_PTR)g_hbrBackground; // Where casting happens
//      return BrushExists(g_hbrBackground); // Tried this to understand things
    }
        break;
//... Other code skipped copy pasting ...
}

代码编译并发出警告:C4244: 'return': conversion from 'LONG_PTR' to 'BOOL', possible loss of data

投射工作,对话框按预期颜色正确: Black colored dialog.

我的问题:当HBRUSH从返回BOOL的函数(DLGPROC)返回为LONG_PTR时,后台会发生什么?我从阅读C ++的假设是,如果LONG_PTR非零,则返回的BOOL为TRUE,如果LONG_PTR为零,则返回的BOOL为FALSE。为了检查这一点,我创建了函数BOOL BrushExists(HBRUSH hBrush);// See code。使用此函数检查HBRUSH并返回TRUE,编译时没有警告并且运行没有错误。但是对话框的颜色不会发生: Black color missing.

所以我的假设是错误的。 {000}似乎将LONG_PTR评估为数字而不是BOOL。有人可以向我解释这是怎么回事吗?

2 个答案:

答案 0 :(得分:3)

请注意,它是BOOL而不是bool。使用Windows SDK,BOOLint的typedef,可以存储32位值 - 它不是一个只能存储true或{{}的简单布尔值1}}。

这基本上是API中的一个kludge。在32位Windows中,刷柄处于32位值,即使它很丑陋且可能令人困惑,它也是安全的#34;返回一个刷子手柄强制转换为false(你必须强制转换它,因为BOOL被定义为返回)。

一旦Windows获得64位支持,这种情况显然是不可接受的 - 在这个例子中,刷柄(指针)的大小是64位 - 将它们转换为32位类型是不安全的

因此,DialogProc的定义已更改为返回DialogProc而不是INT_PTR。这个类型定义为x86中的32位和x64中的64位。您使用的示例代码显然是在此更改之前,但所有新代码都应使用BOOL的正确定义作为返回DialogProc

答案 1 :(得分:0)

  • int只是LONG_PTR typedef&#39; d。
  • long int可以是__int64#ifdef _WIN64 typedef __int64 LONG_PTR; #else typedef long LONG_PTR; #endif - 取决于所选择的平台。

来自标题:

BOOL

您似乎将项目构建为x64编译器,因此LONG_PTRint(基本上是int64int)会向您发出警告。

请注意,{C <1}和long在Visual C ++ / Windows上基本相同。