理论
C 库宏 offsetof(type, member-designator) 会生成一个类型为 size_t 的整型常量,它是一个结构成员相对于结构开头的字节偏移量。成员是由 member-designator 给定的,结构的名称是在 type 中给定的。
/*
* 参数: type -- 这是一个 class 类型,其中,member-designator 是一个有效的成员指示器。
* member-designator -- 这是一个 class 类型的成员指示器。
* 返回值: 该宏返回类型为 size_t 的值,表示 type 中成员的偏移量
*/
offsetof(type, member-designator)
实践
#include <stddef.h>
#include <stdio.h>
struct address {
char name[50];
char street[50];
int phone;
};
int main()
{
printf("address 结构中的 name 偏移 = %d 字节。\n",
offsetof(struct address, name));
printf("address 结构中的 street 偏移 = %d 字节。\n",
offsetof(struct address, street));
printf("address 结构中的 phone 偏移 = %d 字节。\n",
offsetof(struct address, phone));
return(0);
}
#include <stddef.h>
#include <stdio.h>
struct MBLOCK {
size_t signature;
size_t length;
union {
size_t align;
char payload[1]; /* actually a bunch of bytes */
} u;
}MBLOCK;
int main()
{
printf("MBLOCK 结构中的 signature 偏移 = %lu 字节。\n",
offsetof( struct MBLOCK, signature)); // 0
printf("MBLOCK 结构中的 length 偏移 = %lu 字节。\n",
offsetof(struct MBLOCK, length)); // 8
printf("MBLOCK 结构中的 u 偏移 = %lu 字节。\n",
offsetof(struct MBLOCK, u)); // 16
printf("MBLOCK 结构中的 u.align 偏移 = %lu 字节。\n",
offsetof(struct MBLOCK, u.align)); // 16
printf("MBLOCK 结构中的 u.payload[0] 偏移 = %lu 字节。\n",
offsetof(struct MBLOCK, u.payload[0])); // 16
printf("MBLOCK 结构中的 u.payload[1] 偏移 = %lu 字节。\n",
offsetof(struct MBLOCK, u.payload[1])); // 17
printf("MBLOCK 结构中的 u.payload[2] 偏移 = %lu 字节。\n",
offsetof(struct MBLOCK, u.payload[2])); // 18
printf("MBLOCK 结构中的 u.payload[12] 偏移 = %lu 字节。\n",
offsetof(struct MBLOCK, u.payload[12])); // 28
return(0);
}
offsetof
作用是 相对于结构体开始的内存地址偏移了多少
当然,我们可以给结构体起一个别名,这样就不需要每次都创建一个结构体了(结果和上面是一样的)
#include <stddef.h>
#include <stdio.h>
typedef struct MBLOCK {
size_t signature;
size_t length;
union {
size_t align;
char payload[1]; /* actually a bunch of bytes */
} u;
}MBLOCK;
int main()
{
printf("MBLOCK 结构中的 signature 偏移 = %lu 字节。\n",
offsetof( MBLOCK, signature)); // 0
printf("MBLOCK 结构中的 length 偏移 = %lu 字节。\n",
offsetof( MBLOCK, length)); // 8
printf("MBLOCK 结构中的 u 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u)); // 16
printf("MBLOCK 结构中的 u.align 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u.align)); // 16
printf("MBLOCK 结构中的 u.payload[0] 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u.payload[0])); // 16
printf("MBLOCK 结构中的 u.payload[1] 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u.payload[1])); // 17
printf("MBLOCK 结构中的 u.payload[2] 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u.payload[2])); // 18
printf("MBLOCK 结构中的 u.payload[2] 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u.payload[12])); // 28
return(0);
}
#include <stddef.h>
#include <stdio.h>
typedef struct MBLOCK {
size_t signature;
size_t length;
union {
size_t align;
char payload[1]; /* actually a bunch of bytes */
} u;
}MBLOCK;
int main()
{
printf("MBLOCK 结构中的 signature 偏移 = %lu 字节。\n",
offsetof( MBLOCK, signature) + 4);
printf("MBLOCK 结构中的 length 偏移 = %lu 字节。\n",
offsetof( MBLOCK, length) + 100); // 108 ----> 它的意思是先找到offsetof( MBLOCK, length),然后在偏移100.不会影响原来的内存
printf("MBLOCK 结构中的 u 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u)); // 16
printf("MBLOCK 结构中的 u.align 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u.align) ); // 16
printf("MBLOCK 结构中的 u.payload[0] 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u.payload[0])); // 16
printf("MBLOCK 结构中的 u.payload[1] 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u.payload[1])); // 17
printf("MBLOCK 结构中的 u.payload[2] 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u.payload[2])); // 18
printf("MBLOCK 结构中的 u.payload[2] 偏移 = %lu 字节。\n",
offsetof( MBLOCK, u.payload[12])); // 28
return(0);
}
我们可以使用结果体来找到相对某个内存地址偏移多少
#include <stddef.h>
#include <stdio.h>
typedef struct MBLOCK {
size_t signature;
size_t length;
union {
size_t align;
char payload[1]; /* actually a bunch of bytes */
} u;
}MBLOCK;
#define SPACE_FOR(len) (offsetof(MBLOCK, u.payload[0]) + len)
int main()
{
printf("相对MBLOCK 结构中的 u.payload[0] 偏移 4字节 = %lu 字节。\n", SPACE_FOR(4)); // 20
printf("相对MBLOCK 结构中的 u.payload[0] 偏移 84字节 = %lu 字节。\n", SPACE_FOR(84)); // 100
printf("相对MBLOCK 结构中的 u.payload[0] 偏移 -16字节= %lu 字节。\n", SPACE_FOR(-16));
return(0);
}