c语言的结构比较好玩,它的指针偏移特别有意思。
下面的宏定义也很奇怪:
#define offsetof(type, number) (size_t)&(( (type *)0) -> number)
开始我以为这个不会通过编译,因为当时我对(void *)0比较敏感,就是NULL指针咯。不过这个宏定义确实是正确的。它用于计算结构元素的偏移量(字节数)。试试就知道了。
struct test
{
char a;
int b ;
char c;
};
测试语句如下:
printf("sizeof(struct test) = %d, offsetof(struct test, a) = %d, offsetof(struct test, b) = %d, offsetof(struct test, c) = %d\n", sizeof(struct test), offsetof(struct test, a), offsetof(struct test, b), offsetof(struct test, c));
运行结果如下:
sizeof(struct test) = 12, offsetof(struct test, a) = 0, offsetof(struct test, b) = 4, offsetof(struct test, c) = 8
1、 把上面的结构稍微改一下,测试语句不变。
struct test
{
char a;
char b ;
int c;
};
运行结果如下:
sizeof(struct test) = 8, offsetof(struct test, a) = 0, offsetof(struct test, b) = 1, offsetof(struct test, c) = 4
struct test
{
char a;
char b ;
short c;
};
运行结果:
sizeof(struct test) = 4, offsetof(struct test, a) = 0, offsetof(struct test, b) = 1, offsetof(struct test, c) = 2
还好啦,我自己知道为什么会这样,可是说不上来。简单的讲吧,不同类型之间会出现4字节对齐。也不知道讲的对不对。
以前看到ST的arm结构封装,我很困惑。
typedef struct
{
vu16 CR1;
u16 RESERVED0;
vu16 CR2;
u16 RESERVED1;
vu16 SMCR;
u16 RESERVED2;
vu16 DIER;
u16 RESERVED3;
vu16 SR;
u16 RESERVED4;
vu16 EGR;
u16 RESERVED5;
vu16 CCMR1;
u16 RESERVED6;
vu16 CCMR2;
u16 RESERVED7;
vu16 CCER;
u16 RESERVED8;
vu16 CNT;
u16 RESERVED9;
vu16 PSC;
u16 RESERVED10;
vu16 ARR;
u16 RESERVED11;
vu16 RCR;
u16 RESERVED12;
vu16 CCR1;
u16 RESERVED13;
vu16 CCR2;
u16 RESERVED14;
vu16 CCR3;
u16 RESERVED15;
vu16 CCR4;
u16 RESERVED16;
vu16 BDTR;
u16 RESERVED17;
vu16 DCR;
u16 RESERVED18;
vu16 DMAR;
u16 RESERVED19;
} TIM_TypeDef;
#define PERIPH_BASE ((u32)0x40000000)
#define TIM2_BASE (APB1PERIPH_BASE + 0x0000)
#define TIM2 ((TIM_TypeDef *) TIM2_BASE)
这个也算是结构寻址的一个应用吧,使用起来还是很方便的。
2、 如果知道结构里某个元素的地址,这样就可以反推出结构的基址。 这是一个很有用的特性。
struct test
{
char a;
char b ;
int c;
list d;
};
如果list是一个双向链表,那么可以就很容易得到节点的地址,从来反推出结构的基址。不少操作系统的调度就是利用了这个原理。
#definelist_entry(node,type,member) ((type *)((unsigned int)(node) - (unsigned int)(&((type *)0)->member)))
总结:我知道的就这么多了。 水平不咋滴,多多学习。。