这两天在研究字节对齐的问题,偶然看到了博客园某位答主的代码:
/* OFFSET宏定义可取得指定结构体某成员在结构体内部的偏移 */
#define OFFSET(st, field) (size_t)&(((st*)0)->field)
typedef struct{
char a;
short b;
char c;
int d;
char e[3];
}T_Test;
int main(void){
printf("a-%d, b-%d, c-%d, d-%d\n",
OFFSET(T_Test, a),
OFFSET(T_Test, b),
OFFSET(T_Test, c),
OFFSET(T_Test, d));
printf("a-%d\n", (size_t)&(((T_Test*)0)->a));
return 0;
}
这段代码的用途是查看结构中每个字段的偏移地址,程序的输出如下:
a-0, b-2, c-4, d-8
a-0
我的问题是
#define OFFSET(st, field) (size_t)&(((st*)0)->field)
这个宏定义中的 (size_t)&(((st*)0)->field)
是如何起作用的,((st*)0)
不是一个 st* 类型的空指针吗,为什么能够通过它访问 T_Test 中的字段。
((st*)0) 是一个 st* 类型的空指针.
但是这里没有去访问里面的元素,只是%d去打印了地址的值,所以合法,他这样做的目的是为了将a的地址设为0,从而更好的看地址的偏移
T_Test* p = (T_Test*)0;
printf("%d\n",&(p->a));
这样是合法的
但是此时你使用以下就不行了
T_Test* p = (T_Test*)0;
printf("%d\n",p->a);
或者你可以使用%p去打印地址,也是null
T_Test* p = (T_Test*)0;
printf("%p\n",p);