从运行结果我们可以看出上面的几种使用方式,实际上,sizeof计算对象的大小也是转换成对对象类型的计算,也就是说,同种类型的不同对象其sizeof值都是一样的。从给出的代码中我们也可以看出sizeof可以对一个表达式求值,编译器根据表达式的最终结果类型来确定大小,但是一般不会对表达式进行计算或者当表达式为函数时并不执行函数体。如:
|
运行结果为:
|
从结果我们可以看出print()函数并没有被调用。
接下来我们来看看linux内核链表里的一个宏:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
对这个宏的讲解我们大致可以分为以下4步进行讲解:
1、( (TYPE *)0 ) 0地址强制 "转换" 为 TYPE结构类型的指针;
2、((TYPE *)0)->MEMBER 访问TYPE结构中的MEMBER数据成员;
3、&( ( (TYPE *)0 )->MEMBER)取出TYPE结构中的数据成员MEMBER的地址;
4、(size_t)(&(((TYPE*)0)->MEMBER))结果转换为size_t类型。
宏offsetof的巧妙之处在于将0地址强制转换为 TYPE结构类型的指针,TYPE结构以内存空间首地址0作为起始地址,则成员地址自然为偏移地址。可能有的读者会想是不是非要用0呢?当然不是,我们仅仅是为了计算的简便。也可以使用是他的值,只是算出来的结果还要再减去该数值才是偏移地址。来看看下面的代码:
|
运行结果为:
|