发信人: skyonme (sky), 信区: VC
标 题: 【合集】DECLARE_HANDLE(name)怎么解释
发信站: 饮水思源 (2002年01月19日11:39:26 星期六), 站内信件
☆──────────────────────────────────────☆
cantankerous (well..i'm cantankerous) 于 2001年10月22日11:53:32 星期一 提到:
#ifdef STRICT
typedef void *HANDLE;
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct
name##__ *name
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif
typedef HANDLE *PHANDLE;
哪位大虾帮我解释一下这段申明handle的macro..
谢谢
特别是第三句
☆──────────────────────────────────────☆
ose (某某人) 于 2001年10月22日22:28:34 星期一 提到:
看下面这段代码:
HANDLE hWnd=CreateProcess(...);
...
ShowWindow(hWnd,SW_SHOW);
...
一看就知道,程序有问题,因为hProcess是一个进程句柄,最后却当成了窗口句柄
用。
如果STRICT被定义了,对类型匹配要求严格,这时HANDLE被定义成void *,
HWND被定义成指向struct HWND__{int used;/*确实是没用*/}的指针,也就是你将
一个void *赋给一个struct HWND__{int used;} *,编译器肯定是大声哼哼,
于是你就会看看她为什么有意见,结果你发现了这个错误,当然是在编译器
的帮助下发现的。
反之如果STRICT没有定义,同样的代码,编译器会一言不发,编译器高兴,你
也高兴,皆大欢喜,可就是程序出错。
因此,我们写程序最好是定义STRICT宏。MFC默认是定义了STRICT的。
最后,看看下面的代码:
HANDLE hWnd=(HANDLE)CreateWindow(...);
...
ShowWindow((HWND)hWnd);
即使定义了STRICT宏,编译器也会很高兴,你也高兴,程序也正常运行,只是有点bt。
因此可以看出这两种句柄的定义本质上没有区别,只是当定义了STRICT时,编译器可
以帮你找出尽可能多的错误。
☆──────────────────────────────────────☆
Calbon (蓝蓝的衬衫里有花花的格子) 于 2001年10月23日12:13:10 星期二 提到:
恩
昨天在家里用编译器看
然后翻了一下<<the C programming language>>里关于预定义里##的说法
终于明白了
HANDLE者,即void *也
HWND者, struct HWND__ { int unused;} *也;
其他的各种HXXX 也就是struct HXXX__ {int unused;} * ..
当初对这个unused迷惑不解,
现在想想真妙啊,
确实没用到的说,浪费了两个字节换来了四个字节的地址句柄。
那个编windows.h的人是搞笑。
☆──────────────────────────────────────☆
Calbon (蓝蓝的衬衫里有花花的格子) 于 2001年10月23日12:19:42 星期二 提到:
大侠能否再答一下3965
谢谢!
☆──────────────────────────────────────☆
Raney (蜡笔小新~被外星人绑架中) 于 2001年10月23日18:23:36 星期二 提到:
其实,这句最大的问题就在于“##”操作符。
这好像是是宏定义中特有的
##的作用是,把文件中位于它前后的两个字符串连接起来。
比如: moon##cake 在预编译处理后就变成了 mooncake
对于上述语句,在预编译处理时,
首先,name被参数所取代,假设这里name的值是BRUSH,这样就变成了 BRUSH##__
然后,所有的BRUSH##__都变成BURSH__
实际上这是一种编辑技巧,很多情况下都不用,不过对于某些特殊的情况还是很有用的
比如,上述的宏定义中,用来改名等等。
转自:http://bbs.sjtu.edu.cn/bbsanc,path,%2Fgroups%2FGROUP_3%2FVS%2FWindowsDlgs%2Fhandle%2FM.1011411567.A.html