结构体成员变量的偏移值

1、windows平台下有offsetof宏可以求得结构体成员变量便宜,源码如下:
/* Define offsetof macro */
#ifdef __cplusplus

#ifdef  _WIN64
#define offsetof(s,m)   (size_t)( (ptrdiff_t)&reinterpret_cast<const volatile char&>((((s *)0)->m)) )
#else
#define offsetof(s,m)   (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))
#endif

#else

#ifdef  _WIN64
#define offsetof(s,m)   (size_t)( (ptrdiff_t)&(((s *)0)->m) )
#else
#define offsetof(s,m)   (size_t)&(((s *)0)->m)//零地址得出的偏移,相当NULL指针,->符号并没有去执行代码,编译器只是取成员域的地址,避免对象创建,效率大大提高,往往在面试题中出现
#endif

#endif	/* __cplusplus */
2、同样的道理,知道成员变量地址,结构体类型,成员名称,就可以求得:结构体开始地址 = 成员变量地址-offset
windows下有个CONTAINING_RECORD

#define CONTAINING_RECORD(address,type,field) ((type*)((PCHAR)(address)-(ULONG_PTR)(&((type*)0)->field)))

3、Linux的链表和hash表就用到了这种技术

      在linux内核中,链表没有保存数据域,链表节点作为数据节点的域,遍历全局链表或者hash表时,利用上面1、2两点得数据节点的地址。跟一般的链表操作相反。

example 1.1 数据节点结构体

 749struct inode {
 750        umode_t                 i_mode;
 751        unsigned short          i_opflags;
 752        uid_t                   i_uid;
 753        gid_t                   i_gid;
 754        unsigned int            i_flags;
 755
 756#ifdef CONFIG_FS_POSIX_ACL
 757        struct posix_acl        *i_acl;
 758        struct posix_acl        *i_default_acl;
 759#endif
 760
 761        const struct inode_operations   *i_op;
 762        struct super_block      *i_sb;
 763        struct address_space    *i_mapping;
 764
 765#ifdef CONFIG_SECURITY
 766        void                    *i_security;
 767#endif
 768
 769        /* Stat data, not accessed from path walking */
 770        unsigned long           i_ino;
 771        /*
 772         * Filesystems may only read i_nlink directly.  They shall use the
 773         * following functions for modification:
 774         *
 775         *    (set|clear|inc|drop)_nlink
 776         *    inode_(inc|dec)_link_count
 777         */
 778        union {
 779                const unsigned int i_nlink;
 780                unsigned int __i_nlink;
 781        };
 782        dev_t                   i_rdev;
 783        struct timespec         i_atime;
 784        struct timespec         i_mtime;
 785        struct timespec         i_ctime;
 786        spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
 787        unsigned short          i_bytes;
 788        blkcnt_t                i_blocks;
 789        loff_t                  i_size;
 790
 791#ifdef __NEED_I_SIZE_ORDERED
 792        seqcount_t              i_size_seqcount;
 793#endif
 794
 795        /* Misc */
 796        unsigned long           i_state;
 797        struct mutex            i_mutex;
 798
 799        unsigned long           dirtied_when;   /* jiffies of first dirtying */
 800
 801        struct hlist_node       i_hash;  //hash链表
 802        struct list_head        i_wb_list;      /* backing dev IO list */
 803        struct list_head        i_lru;          /* inode LRU list */
 804        struct list_head        i_sb_list;
 805        union {
 806                struct list_head        i_dentry;
 807                struct rcu_head         i_rcu;
 808        };
 809        atomic_t                i_count;
 810        unsigned int            i_blkbits;
 811        u64                     i_version;
 812        atomic_t                i_dio_count;
 813        atomic_t                i_writecount;
 814        const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */
 815        struct file_lock        *i_flock;
 816        struct address_space    i_data;
 817#ifdef CONFIG_QUOTA
 818        struct dquot            *i_dquot[MAXQUOTAS];
 819#endif
 820        struct list_head        i_devices;
 821        union {
 822                struct pipe_inode_info  *i_pipe;
 823                struct block_device     *i_bdev;
 824                struct cdev             *i_cdev;
 825        };
 826
 827        __u32                   i_generation;
 828
 829#ifdef CONFIG_FSNOTIFY
 830        __u32                   i_fsnotify_mask; /* all events this inode cares about */
 831        struct hlist_head       i_fsnotify_marks;
 832#endif
 833
 834#ifdef CONFIG_IMA
 835        atomic_t                i_readcount; /* struct files open RO */
 836#endif
 837        void                    *i_private; /* fs or device private pointer */
 838};
example 1.2 链表定义

       struct list_head {
223 struct list_head *next, *prev;
224 };
225
226 struct hlist_head {
227 struct hlist_node *first;
228 };
229
230 struct hlist_node {
231 struct hlist_node *next, **pprev;
232 };


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
结构体是由多个不同类型的变量组成的数据类型,每个变量在内存中占用不同的空间。结构体类型地址偏移量指的是结构体中每个变量的地址相对于结构体起始地址的偏移量。 在C语言中,可以使用指针来访问结构体中的变量。偏移量可以通过指向结构体的指针加上变量偏移量来计算。例如,假设有以下结构体: ```c struct student { char name[20]; int age; float score; }; ``` 可以定义一个指向该结构体的指针,并使用指针来访问结构体中的变量: ```c struct student stu; struct student *p = &stu; ``` 访问结构体中的变量可以使用点运算符或箭头运算符,例如访问name变量的偏移量可以使用以下代码: ```c int name_offset = (int)&((struct student *)0)->name; ``` 这个表达式中,(struct student *)0将0强制转换为指向结构体类型的指针,然后取出name成员的地址,最后将其转换为int类型。这个偏移量可以用来计算结构体中name变量的地址。 类似地,可以计算age和score变量的偏移量: ```c int age_offset = (int)&((struct student *)0)->age; int score_offset = (int)&((struct student *)0)->score; ``` 使用偏移量可以在不知道结构体起始地址的情况下访问结构体中的变量。例如,可以使用以下代码访问结构体中的name变量: ```c char *name_ptr = (char *)((int)p + name_offset); ``` 这个表达式中,将指向结构体的指针p转换为int类型,然后加上name变量的偏移量,最后将结果转换为指向char类型的指针。这个指针可以用来访问结构体中的name变量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值