请解释这个执行强制转换和类型检查的核心宏

sha*_*oth 9 c c++ macros types casting

以下代码来自必须在C和C++中编译的现有应用程序.有一个宏:

/* Type-checking macro to provide arguments for CoCreateInstance() etc.
 * The pointer arithmetic is a compile-time pointer type check that 'obj'
 * really is a 'type **', but is intended to have no effect at runtime. */
#define COMPTR(type, obj) &IID_##type, \
(void **)(void *)((obj) + (sizeof((obj)-(type **)(obj))) \
                - (sizeof((obj)-(type **)(obj))))
Run Code Online (Sandbox Code Playgroud)

使用如下:

ISomeInterface *object;
CoCreateInstance(&CLSID_SomeInterfaceImpl, NULL,
     CLSCTX_INPROC_SERVER, COMPTR(ISomeInterface, &object))));
Run Code Online (Sandbox Code Playgroud)

这里的想法是,最后的两个参数CoCreateInstance()IID&void**和宏观争夺ISomeInterface**并将其转换为IID&void**在同一时间执行编译时检查到位的传递的地址ISomeInterface**确实是一个地址ISomeInterface*指针变量.

好的,但需要什么

((obj) + (sizeof((obj)-(type **)(obj))) \
     - (sizeof((obj)-(type **)(obj)))
Run Code Online (Sandbox Code Playgroud)

复杂的表达?我看到使用(obj)-(type**)(obj)子表达式强制执行类型检查.有什么需要添加然后减去sizeof()?在铸造void*之前需要铸造void**什么?

我想同样的事情可以做如下:

#define COMPTR(type, obj) &IID_##type, \
(void **)(sizeof((obj)-(type**)(obj)), obj)
Run Code Online (Sandbox Code Playgroud)

这里逗号运算符的第一部分将包含一个sizeof()强制执行类型检查并计算为常量的部分,第二部分只生成相同的指针并且指针将被强制转换为void**.

原始的宏可以做什么,我建议不能?这些并发症有什么需要?

the*_*mel 5

也许原作者不知道逗号运算符?这在C/C++程序员中并不是闻所未闻.