#define XML_GetUserData(parser) (*(void **)(parser))
首先把 parser 转换成 void**;然后再提取 void** 指向的位置,这个位置的类型是 void*。
查资料知道,这个宏用来从 XML_Parser 中得到 user data:
struct XML_ParserStruct {
/* The first member must be userData so that the XML_GetUserData
macro works. */
void *m_userData;
void *m_handlerArg;
char *m_buffer;
const XML_Memory_Handling_Suite m_mem;
/* first character to be parsed */
/* ...... */
};
typedef XML_ParserStruct* XML_Parser
很明显,parser和 &(parser->m_userData)的值是一样的,不一样的是 parser 的数据类型是 XML_Parser;而 &(parser->m_userData) 的数据类型是 void**。
而且很显然 *(&(parser->m_userData)) 就是 parser->m_userData,所以 *(void**)(parser)也完全等价于parser->m_userData。
但是为什么要这么写呢?
先看其它几种写法的写法:
1. pParser->m_userData
没有问题但是需要包含 XML_ParserStructure 的定义。
2.(void*)(pParser)
语义不正确,得到的指针指向 XML_ParserStructure 而不是m_userData 所指的对象。
3.(void*)(*pParser))
语法不正确,不能把 XML_ParserStructure 类型转换成 void*。
回头看,我们面对的结构是:parser->m_userData->something。
我们要得到的是指向 something的指针,而不是指向m_userData的指针。
所以那个 *(void**) 就容易理解了,这样带来的好处可能是用户不需要知道 XML_ParserStructure 的确切定义 —— 虽然也有二进制上的假设和依赖性。