精华内容
下载资源
问答
  • 结构体偏移.docx

    2021-02-08 10:15:39
    结构体偏移
  • c语言——结构体偏移

    2020-05-18 17:26:59
    目录c语言——结构体偏移整数类型浮点类型例子结构体成员偏移量test01test02test03参考资料 c语言——结构体偏移 学习结构体偏移前,我们先复习一下c语言的数据类型 整数类型 下表列出了关于标准整数类型的存储大小...

    c语言——结构体偏移

    学习结构体偏移前,我们先复习一下c语言的数据类型、结构体对齐。

    整数类型

    下表列出了关于标准整数类型的存储大小和值范围的细节:

    类型存储大小值范围
    char1 字节-128 到 127 或 0 到 255
    unsigned char1 字节0 到 255
    signed char1 字节-128 到 127
    int2 或 4 字节-32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
    unsigned int2 或 4 字节0 到 65,535 或 0 到 4,294,967,295
    short2 字节-32,768 到 32,767
    unsigned short2 字节0 到 65,535
    long4 字节-2,147,483,648 到 2,147,483,647
    unsigned long4 字节0 到 4,294,967,295

    注意,各种类型的存储大小与系统位数有关,但目前通用的以64位系统为主。
    以下列出了32位系统与64位系统的存储大小的差别(windows 相同):

    为了得到某个类型或某个变量在特定平台上的准确大小,您可以使用 sizeof 运算符。表达式 sizeof(type) 得到对象或类型的存储字节大小。

    浮点类型

    下表列出了关于标准浮点类型的存储大小、值范围和精度的细节:

    类型存储大小值范围精度
    float4 字节1.2E-38 到 3.4E+386 位小数
    double8 字节2.3E-308 到 1.7E+30815 位小数
    long double16 字节3.4E-4932 到 1.1E+493219 位小数

    结构体对齐

    结构体计算要遵循字节对齐原则。

    结构体默认的字节对齐一般满足三个准则:

    • 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
    • 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
    • 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)

    结构体大小的计算

    例子

    #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);
    }
    

    运行

    address 结构中的 name 偏移 = 0 字节。
    address 结构中的 street 偏移 = 50 字节。
    address 结构中的 phone 偏移 = 100 字节。
    

    结构体成员偏移量

    test01

    struct A
    {
    	char a1; //0
    	int a2; //4-7
    };
    
    void test01()
    {
    
    	struct A a = { 'b', 20 };
    	printf("A.a2:%d\n", *(int *)((char *)&a + offsetof(struct A, a2)));
    	printf("A.a2:%d\n",   *((int *)&a + 1)   );
    
    }
    

    运行

    A.a2:20
    A.a2:20
    

    test02

    struct B
    {
    	char a;
    	int b;
    	struct C c;
    };
    
    void test02()
    {
    	struct B b = { 'a', 20, 30, 3.14 };
    
    	int off1 = offsetof(struct B, c);
    	int off2 = offsetof(struct C, b);
    
    	printf("off1=%d\n", off1);
    	printf("off2=%d\n", off2);
    
    	printf("%f\n", *(double *)(((char *)&b + off1) + off2));
    	printf("%d\n", &(b.c.b));
    	printf("%f\n", ((struct C *)((char *)&b + off1))->b );
    }
    

    运行

    off1=8
    off2=8
    3.140000
    11533292
    3.140000
    

    test03

    struct Student{
    	int a; //0-3
    	char b; //4-7
    	double c; //8-15
    	float d;//16-19
    };
    
    void test03()
    {
    	printf("%d\n", sizeof(struct Student));
    }
    

    运行

    24
    

    因为结构体对齐,所以8 * 3 = 24

    参考资料

    C 库宏-offsetof()
    C 标准库-<stddef.h>
    C 数据类型

    展开全文
  • 结构体偏移

    2021-05-07 14:14:55
    结构体偏移量 可以利用offsetof来计算结构体中属性的偏移 也可以通过地址的相加运算 计算偏移量 结构体嵌套结构体 代码示例: #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h>...

    结构体偏移量

    • 可以利用offsetof来计算结构体中属性的偏移
    • 也可以通过地址的相加运算 计算偏移量
    • 结构体嵌套结构体

    代码示例:

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<stddef.h>
    struct Person
    {
            char a; //0~3
            int b;  //4~7
    };
    void test01()
    {
            struct Person p1;
            struct Person *p = &p1;
            printf("b的偏移量为:%d\n", (int)&(p->b)-(int)p);
            printf("b的偏移量为:%d\n",offsetof(struct Person,b));
    }
    //通过偏移量   获取到数据
    void test02()
    {
            struct Person p1 = {'a',10};
            printf("p.b=%d\n",*(int*)((char*)&p1+offsetof(struct Person,b)));
            printf("p.b=%d\n", *(int*)(int*)&p1 + 1);
    }
    //结构体嵌套结构体
    struct Person2
    {
            char a;
            int b;
            struct Person c;
    };
    void test03()
    {
            struct Person2 p = { 'a',10,'b',20 };
            int offset1 = offsetof(struct Person2,c);
            int offset2 = offsetof(struct Person, b);
            printf("%d\n",*(int*)((char*)&p+offset1+offset2));
            printf("%d\n",((struct Person*)((char*)&p+offset1))->b);
    }
    int main()
    {
            //test01();
            //test02();
            test03();
            return EXIT_SUCCESS;
    }
    
    展开全文
  • 主要介绍了C语言中结构体偏移及结构体成员变量访问方式的问题讨论,帮助大家理解struct的成员变量偏移,需要的朋友可以参考下
  • 利用结构体成员偏移量和结构体成员地址结构体地址 1. 前言 在实际项目开发中,发现了两个有意思的宏定义。 #define offsetof(type, member) ((unsigned long)(&((type *)0)->member)) #define LIST_ENTRY...

    利用结构体成员偏移量和结构体成员地址求结构体的地址

    1. 前言

    在实际项目开发中,发现了两个有意思的宏定义。

    #define offsetof(type, member) ((unsigned long)(&((type *)0)->member))

    #define LIST_ENTRY(optr, type, member) ((type *)((char *)(optr) - offsetof(type, member)))

    第一个是求结构体成员的偏移量。假设在地址0处有一个type类型的结构体,由于结构体的基地址是0,所以member的地址就是其偏移量。你也可以在地址0x1处假设,那么其定义为:#define offsetof(type, member) ((unsigned long)(&((type *)0x1)->member) – 0x1),看起来还是在0处比较简洁。

    第二个宏定义是假如你知道某个结构体成员的地址,那么通过其偏移量可以求出结构体的地址。其中optr是结构体成员的地址,type是结构体类型,member是结构体成员。其实很好理解,成员的地址减去成员的偏移量即为结构体的首地址。

    下面通过一个例子进一步理解。

    2. 代码

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    #define offsetof(type, member) ((unsigned long)(&((type *)0)->member))
    //#define offsetof(type, member) ((unsigned long)(&((type *)0x1)->member) - 0x1)
    #define LIST_ENTRY(optr, type, member)   ((type *)((char *)(optr) - offsetof(type, member)))
    
    typedef struct _Person_{
            int id;
            char name[32];
            long long next;
    }person_t;
    
    int main()
    {
            person_t *lee = (person_t *)malloc(sizeof(person_t));
    
            lee->id = 1;
            strcpy(lee->name,"lee");
    
            printf("next offset is %d\n",offsetof(person_t,next));
            printf("lee addr:%p,next:%p\n",lee,&lee->next);
    
            char *p = &lee->next;
    
            person_t *lee2 = LIST_ENTRY(p,person_t,next);
            printf("lee2:%p,id:%d,name:%s\n",lee2,lee2->id,lee2->name);
    }
    
    

    编译运行结果如下:

    从结果可以看到,next的偏移量是40。奇怪int是4个字节,加上32应该是36才对啊。从打印的地址上看,这里涉及到了字节的对齐。由于next成员是long long类型,是8字节,所以整个结构体8字节对齐。因此next是偏了4个字节的。所以偏移量是40。
    我们把lee结构中的next的地址保存到p里面。根据LIST_ENTRY这个宏,求到的lee2的地址即为lee的地址,因此打印的结果即是lee结构的结果。

    3. 应用场景

    通常我们的使用场景是在哈希链表中应用。我们的结构体中有一个next成员,next指向下一个结构的next。在遍历链表时,通过next的地址,即可以求出结构体的地址。进而进行查找比较操作。

    4. 总结

    1. 求结构体偏移量的方法
    2. 结构体对齐,导致结构体变大。
    3. 根据成员地址求结构体首地址的方法。
    展开全文
  • 结构体偏移量:所谓偏移量,就是我们每个结构体成员的首地址而已。 1 求结构体成员偏移量的两中办法 1)简单求结构体成员偏移量 。 // 注意:求偏移量时,必须将地址转成int整数才能求偏移量,不能直接地址相减,...

    01内存对齐之结构体偏移量

    前提概念
    结构体偏移量:所谓偏移量,就是我们每个结构体成员的首地址而已。

    1 求结构体成员偏移量的两中办法
    1)简单求结构体成员偏移量 。
    // 注意:求偏移量时,必须将地址转成int整数才能求偏移量,不能直接地址相减,否则会默认先转成int型,4字节对应1个int。

    typedef struct TEACHER {
    	char name[4];
    	int  age;
    	int  id;
    }Teacher;
    int main(){
    	Teacher t1;
    	Teacher *p = &t1;
    	int size1 = (int)(&p->age) - (int)p;   // &(p->age)表示取存放age值的首地址 
    	printf("%d\n", size1);
    	
    	return 0;
    }
    
    

    2)绝对零地址法求。

    // 每个结构体内部均有一个绝对零地址即结构体首地址(这里指p) 写法为"(类型 *)0"
    	int size2 = (int)&(((Teacher*)0)->age);
    	printf("%d\n", size2);
    

    2 完整代码测试与结果分析
    1)测试

    #include<stdio.h>
    
    typedef struct TEACHER {
    	char name[4];
    	int  age;
    	int  id;
    }Teacher;
    
    void test01() {
    	
    	Teacher t1;
    	Teacher *p = &t1;
    
    	printf("%x\n", &p->age);
    	printf("%x\n", p);
    
    	// 两种错误求法测试
    	printf("%x\n", (&p->age - p));  // 地址相减后会默认转成int 0xc - 0x8=4字节,刚好对应1个int. 所以再以%x输出实际已经是1了
    	int size = (int)(&p->age - p);
    	printf("%d\n", size);
    
    	// 正确求法测试
    	int n1 = (int)(&p->age);
    	printf("%d\n", n1);
    	int n2 = (int)(p);
    	printf("%d\n", n2);
    
    
    	// 1 简单求结构体成员偏移量            // 注意:必须转成int整数才能求偏移量,不能直接地址相减,否则会默认先转成int型 4字节对应1个int
    	int size1 = (int)(&p->age) - (int)p;   // &(p->age)表示取存放age值的首地址 
    	printf("%d\n", size1);
    
    	// 2 绝对零地址法求
    	// 每个结构体内部均有一个绝对零地址即结构体首地址(这里指p) 写法为"(类型 *)0"
    	int size2 = (int)&(((Teacher*)0)->age);
    	printf("%d\n", size2);
    }
    
    int main() {
    	test01();
    	// 总结:结构体内部偏移量以0开始。
    
    	return 0;
    }
    

    2)结果分析
    在这里插入图片描述

    展开全文
  • 结构体偏移计算

    2020-12-28 19:29:37
    很早以前遇到的一道面试题,最近突然有类似需要突然想起来。 #define offset_of(type, memb) \ ((unsigned long)(&((type *)0)->memb))
  • C语语言言中中结结构构体体偏偏移移及及结结构构体体成成员员变变量量访访问问方方式式的的问问题题讨讨论论 这篇文章主要介绍了C语言中结构体偏移及结构体成员变量访问方式的问题讨论,帮助大家理解struct的成员变量...
  • 关于C语言结构体偏移的一点思考

    千次阅读 2016-06-01 15:34:45
    本文将和大家一起分享下,本人最近关于c语言中结构体偏移的一些思考和总结。 另外这篇博文还可以帮你更好的理解这个问题c语言中两种宏定义的区别,关于这个思考有哪些方面的意义,细心的你可能发现本文所属的类别为...
  • 关于c语言结构体偏移的一点思考

    千次阅读 2018-08-03 17:16:27
    注:此处只是利用了编译器的特性来计算结构体偏移 这句话就一笔带过,说得有点牵强附会。以后有时间自己再详细了解一下编译器的特性。。。 more exceptional c++ 中文版 26页   ...相信大家在c语言程序开发的过程...
  • 打印结构体偏移

    2017-01-06 10:22:22
    转载自:http://blog.csdn.net/kelsel/article/details/53506283 #define OFFSET(x, y) &((x *)0)->y struct TestStruct { int mVar1; int mVar2; int mVar3;}; void ...fprintf(stder
  • 一、结构体变量的定义与使用 1.先声明结构体类型再定义变量名 #define _CRT_SECURE_NO_WARNINGS #include <string.h> #include <stdio.h> struct student { char name[21]; int age; char address...
  • 零指针和结构体偏移量 转自:http://hi.baidu.com/debugtime/item/42ce11ca5d063d24ef4665c6 定义一个结构体 struct A { ... int a; char b; short c; ... } 其中已知int a=100; ...
  • 计算结构体偏移量的函数多描述如下:#define offsetof(s,m) (size_t)&(((s *)0)->m) // Microsoft x86 compiler (version 7) #define offsetof(s,m) (size_t)(unsigned long)&(((s *)0)->m) // Diab Coldfire...
  • 文章目录一、结构体基本使用二、结构体常见赋值问题及解决三、结构体与一级指针嵌套四、结构体与二级指针嵌套五、结构体偏移量六、内存对齐问题 一、结构体基本使用 基本规则与使用方法: 1.正常结构体定义时不能赋...
  • 结构体偏移的计算

    2009-11-08 21:31:00
    不通过访问成员变量,求结构体中成员变量的偏移。struct tagData{ int nDay; int nMonth; int nYear;};tagData* p = NULL;printf("%08x", &p->nYear);printf("%08x", &((tagData*)NULL)->nYear);// stType---...
  • 把这个地址强制转换成 size_t 类型,就相当于结构体成员相对于首地址偏移量 #define Offset(type ,exp) ((int)(&((type*)0)->exp)) struct Student {  char s_id[10];  char s_name[10];  char s_...
  • 结构体偏移的小技巧

    2011-10-20 08:21:11
    获取一个结构体中某元素的偏移量 可以采用下面的方法 struct TESTSTRUCT {  int num1;  int num2;  char szName[2]; }; void* offset; offset = &(((struct TESTSTRUCT * )0)->num2); 这里...
  • 欢迎点击「算法与编程之美」↑关注我们!本文首发于微信公众号:"算法与编程之美",欢迎关注,及时了解更多此系列文章。1 引言结构体是c语言中非常重要的一种数据结构,它在原有...
  • 欢迎点击「算法与编程之美」↑关注我们!本文首发于微信公众号:"算法与编程之美",欢迎关注,及时了解更多此系列博客。1 问题定义已知结构体类型定义如下:structnod...
  • 结构体成员偏移地址

    千次阅读 2013-03-09 13:46:36
    中午,一位同事问我一个问题把我问住了: #define MY_OFFSET(MyStruct,MyField) (size_t)&(((MyStruct*)0)->MyField)。...上面定义的MY_OFFSET宏就是要的MyField的偏移。这样强制转换后的结构指针怎么可以用来访问
  • 注:此处只是利用了编译器的特性来计算结构体偏移,并未对内存地址0有任何操作,有些同学对此可能还有些疑问,详细的了解该问题可参考关于c语言结构体成员变量访问方式的一点思考。 此时,我们的偏移求法就消除了...
  • 【已解决】一段使用宏定义求结构体偏移量的C代码 用一个宏定义FIND求一个结构体struc里某个变量相对于struc的偏移量,如FIND(student,a)//等于0 FIND(student,b)//等于4 #include<stdio.h>#...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 61,377
精华内容 24,550
关键字:

结构体偏移地址