精华内容
下载资源
问答
  • 结构体首地址的偏移量
    千次阅读
    2021-07-18 13:12:18


    1 不同类型指针的偏移步长

    (1)不同类型的指针 +1 时,内存偏移的字节数不同。

    char *类型指针 + 1,内存偏移 1 字节;
    int *类型指针 + 1,内存偏移 4 字节;
    double *类型指针 + 1,内存偏移 8 字节。

    示例:

    #include <stdio.h>
    
    //1.不同类型的指针+1时,偏移的字节数不同
    void func1() {
    	char* p = NULL;
    	printf("%p\n", p);		//00000000
    	printf("%p\n", p + 1);	//00000001
    
    	int* pp = NULL;
    	printf("%p\n", pp);		//00000000
    	printf("%p\n", pp + 1);	//00000004
    }
    

    (2)对不同类型的指针解引用时,取出的字节数不同

    示例:

    #include <stdio.h>
    #include <string.h>
    
    //2.对不同类型的指针解引用时,取出的字节数不同
    void func2() {
    	char buff[1024] = { 0 };
    	int num = 1234;
    	//memset(buff, 0, sizeof(buff));
    	memcpy(buff, &num, sizeof(num));
    	
    	char* p = buff;
    	//将char*指针强转为int*类型指针后,再解引用
    	printf("%d\n", *(int *)p);	//1234
    }
    
    //3.对不同类型的指针解引用时,取出的字节数不同
    void func3() {
    	char buff[1024] = { 0 };
    	int num = 1234;
    	//memset(buff, 0, sizeof(buff));
    	memcpy(buff + 1, &num, sizeof(num));
    
    	char* p = buff;
    	//将char*指针强转为int*类型指针后,再解引用
    	printf("%d\n", *(int*)(p + 1));	//1234
    }
    

    2 结构体成员的偏移量

    头文件<stddef.h>定义了标准宏
    offsetof()宏可计算结构体成员的偏移量offsetof(结构体类型名 , 结构体成员名)
    例:offsetof(struct Object, field);

    示例:

    #include <stdio.h>
    #include <stddef.h>		//使用标准宏
    
    //结构体内存对齐(按数据类型长度最大的对齐-double 8字节对齐)
    struct Object {
    	char a;			//0 ~ 3
    	int b;			//4 ~ 7
    	char buff[64];	//8 ~ 71
    	double c;		//72 ~ 79
    };
    
    int main() {
    	struct Object obj = { 'a', 1, "hello world", 3.14 };
    	/*
    		offsetof()宏可计算结构体成员的偏移量(需包含<stddef.h>头文件)
    		offsetof(结构体类型名 , 结构体成员名)
    	*/
    	printf("%d\n", offsetof(struct Object, a));		//0
    	printf("%d\n", offsetof(struct Object, b));		//4
    	printf("%d\n", offsetof(struct Object, buff));	//8
    	printf("%d\n", offsetof(struct Object, c));		//72
    
    	/* 
    		通过结构体成员的指针偏移,可访问各个结构体成员
    		将指向结构体的指针强转为(char *)类型,每次指针偏移的步长为1
    	*/
    	struct Object* p = &obj;
    	//char*类型的起始地址,加上结构体成员的偏移量,再强转为指定结构体成员对应的指针类型,解引用获取指定结构体成员的值
    	printf("%c\n", *( (char*)p + offsetof(Object, a) ));			//a (ASCII码 97)
    	printf("%d\n", *(int *)( (char*)p + offsetof(Object, b) ));		//1
    	//打印输出字符串类型时,无需解引用,使用字符串的首地址即可(默认至'\0'结束)
    	printf("%s\n", ( (char*)p + offsetof(Object, buff) ));			//hello world
    	printf("%lf\n", *(double *)( (char*)p + offsetof(Object, c) ));	//3.140000
    
    	//通过结构体成员的偏移地址,解引用并修改对应结构体成员的值
    	*(double *)((char*)p + offsetof(struct Object, c)) = 3.1415926;	//修改结构体成员c的值
    	printf("%lf\n", *(double *)((char*)p + offsetof(Object, c)));	//3.141593
    
    	return 0;
    }
    

    3 嵌套结构体成员的偏移量

    #include <stdio.h>
    #include <stddef.h>
    
    struct Inner {
        char a;
        int b;
    };
    
    struct Outer {
        char c;
        int d;
        struct Inner inner;
    };
    
    int main() {
        struct Outer outer = { 'a', 1, {'b', 2} };
    
        /* 获取Outer结构体中嵌套的Inner结构体成员b */
        //1.通过结构体变量访问
        printf("%d\n", outer.inner.b);  //2
    
        //2.通过2次指针偏移:
        //(1)先获取嵌套结构体成员inner相对outer的偏移
        int offset1 = offsetof(struct Outer, inner);
        //(2)再获取属性b相对结构体inner的偏移
        int offset2 = offsetof(struct Inner, b);
        printf("%d\n", *(int*)((char*)&outer + offset1 + offset2));     //2
    
        //3.通过1次指针偏移,获取指向嵌套结构体inner的指针,通过结构体指针访问成员
        printf("%d\n", ((struct Inner*)((char*)&outer + offset1))->b);  //2
    
        return 0;
    }
    

    4 结构体的内存对齐

    4.1 内存对齐的原因与优点

    内存未对齐的问题:CPU按块读取内存,当CPU访问数据时,若内存未对齐,则可能导致二次访问的情况,即前后两次访问的数据需拼接后才能获取指定数据。

    内存对齐的优点以空间换时间,浪费部分用于对齐的空间,通过一次访问即可获取指定数据。


    4.2 结构体内存对齐的规则

    (1)内置数据类型:数据存储在该类型大小的整数倍上。

    (2)自定义数据类型:依照特定的对齐规则。
    ①从第1个属性开始,从 偏移量0位置 开始存储;
    ②从第2个属性开始,从 该数据类型大小对齐模数较小值的整数倍开始存储。即min {该数据类型大小 , 对齐模数} 的整数倍
    ③整体计算完毕后进行二次对齐,结构体的总大小必须是 该结构体中最大数据类型对齐模数较小值的整数倍不足需补齐。即min {该结构体中最大数据类型 , 对齐模数} 的整数倍

    注:使用#pragma pack(show)生成代码后查看”杂注”即默认对齐模数。默认对齐模数为8。
    例:pragma pack(show) 的值 == 8

    示例1:按默认对齐模数(8)对齐

    #include <stdio.h>
    //#pragma pack(show)	//对齐模数默认为8	//生成后查看
    
    typedef struct {
    	int a;		//0 ~ 3
    	char b;		//4 → 4 ~ 7				//double对齐后,补为4 ~ 7
    	double c;	//8 ~ 15
    	float d;	//16 ~ 19 → 16 ~ 23		//二次对齐,补为16 ~ 23
    } StructA;
    
    int main() {
    	printf("%d\n", sizeof(StructA));	//24
    
    	return 0;
    }
    

    示例2:按指定对齐模数(1)对齐

    #include <stdio.h>
    #pragma pack(1)	//对齐模数为1
    
    typedef struct {
    	int a;		//0 ~ 3
    	char b;		//4			//对齐模数为1,无需补齐
    	double c;	//5 ~ 12
    	float d;	//13 ~ 16	//二次对齐,对齐模数为1,无需补齐
    } StructB;
    
    int main() {
    	printf("%d\n", sizeof(StructB));	//17
    
    	return 0;
    }
    

    4.3 结构体嵌套结构体时的对齐规则

    ①从第1个属性开始,从 偏移量0位置 开始存储;
    ②从第2个属性开始的非嵌套结构体属性,从 该数据类型大小对齐模数较小值的整数倍开始存储。即min {该数据类型大小 , 对齐模数} 的整数倍
    ③从第2个属性开始的嵌套结构体属性,从 该嵌套结构体中最大数据类型对齐模数较小值的整数倍开始存储。即min {该嵌套结构体中最大数据类型 , 对齐模数} 的整数倍
    ④整体计算完毕后进行二次对齐,结构体的总大小必须是 该结构体中最大数据类型对齐模数较小值的整数倍不足需补齐。即min {该结构体中最大数据类型 , 对齐模数} 的整数倍

    示例:结构体嵌套结构体时,按默认对齐模数(8)对齐

    #include <stdio.h>
    #include <stddef.h>
    
    //默认对齐模数为8
    typedef struct {
    	int a;		//0 ~ 3
    	char b;		//4 → 4 ~ 7				//double对齐后,补为4 ~ 7
    	double c;	//8 ~ 15
    	float d;	//16 ~ 19 → 16 ~ 23		//二次对齐,补为16 ~ 23
    } Inner;		//对齐模数为8时,二次对齐后,Inner结构体的大小为24
    
    typedef struct {
    	int x;		 //0 ~ 3
    	char y;		 //4 → 4 ~ 7  //嵌套结构体inner对齐后,补为4 ~ 7
    	Inner inner; //8 ~ 31	  //按嵌套结构体inner的最大数据类型(8)和对齐模数 对齐
    	float z;	 //32 ~ 35 → 32 ~ 39	//二次对齐,补为32 ~ 39
    } Outer;		 //对齐模数为8时,二次对齐后,Outer结构体的大小为40
    
    
    int main() {
    	printf("内层结构体大小:%d\n", sizeof(Inner));	//24
    	printf("外层结构体大小:%d\n", sizeof(Outer));	//40
    
    	printf("属性x的偏移:%d\n", offsetof(Outer , x));			//0
    	printf("属性y的偏移:%d\n", offsetof(Outer , y));			//4
    	printf("属性inner的偏移:%d\n", offsetof(Outer , inner));	//8
    	printf("属性z的偏移:%d\n", offsetof(Outer , z));			//32
    
    	return 0;
    }
    
    更多相关内容
  • 在使用C语言对STM32编程的过程中,经常使用到结构体,本文介绍了一种得到结构体中一个field的偏移量的方法。
  • 一、结构体成员偏移量、 二、完整代码示例





    一、结构体成员偏移量



    获取 Student 结构体中 age 成员偏移量 有 2 2 2 种写法 ;

    • 结构体样式 :
    typedef struct Student
    {
        char name[5];	// 0 ~ 4 字节
        int age;		// 5 ~ 8 字节
        char *address; // 9 ~ 12 字节
    }Student;
    
    • 0 内存空间 , 按照 Student 结构体内存类型 进行解析 , 可以求出结构体某个 成员 相对于 0 的偏移量 ;
    int offset = (int)&(((Student *)0)->age)
    
    • 先获取 结构体 成员 , 然后再取该成员的地址 ;
    Student student = NULL;
    int offset = (int)&(student->age);
    

    上述两种获取 Student 结构体中 age 成员偏移量的方法是等效的 ;


    结构体 成员的 偏移量 是可以直接 计算获取的 , 不管有没有实际的 结构体变量 ;


    结构体变量 如果声明完成 , 那么结构体中的 成员 的内存 , 就已经分配好了 ;

    如果知道了 结构体成员 的内存地址 , 可以根据该 结构体成员 的偏移量 , 计算出该结构体的 首地址 ;





    二、完整代码示例



    完整代码示例 :

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /**
     * @brief The Student struct
     * 定义 结构体 数据类型 , 同时为该结构体类型声明 别名
     * 可以直接使用 别名 结构体变量名 声明结构体类型变量
     * 不需要在前面添加 struct 关键字
     */
    typedef struct Student
    {
        // 声明变量时 , 会自动分配这 5 字节内存
        // 赋值时 , 可以直接使用 = 赋值字符串
        char name[5];	// 0 ~ 4 字节
        int age;		// 5 ~ 8 字节
    
        // 声明变量时 , 只会为 4 字节指针分配内存
        // 具体的 字符串内存 需要额外使用 malloc 申请内存
        // 赋值时 , 必须使用 strcpy 函数 , 向堆内存赋值
        char *address; // 9 ~ 12 字节
    }Student;
    
    /**
     * @brief 主函数入口
     * @return
     */
    int main()
    {
        // 声明结构体变量
        Student s1;
        // 声明结构体指针
        Student *p = NULL;
    
        // 对指针进行算术运算时合法的
        p = p - 1;
        p = p + 10;
    
        // 给指针 p 设置合法地址
        p = NULL;
    
        // 获取 Student 结构体 age 成员偏移量
        int age_offset = (int)&(p->age);
    
        // 获取 Student 结构体 address 成员偏移量
        int address_offset = (int)&(((Student *)0)->address);
    
        printf("age_offset = %d, address_offset = %d\n", age_offset, address_offset);
    
        // 命令行不要退出
        system("pause");
        return 0;
    }
    

    执行结果 :

    age_offset = 8, address_offset = 12
    请按任意键继续. . .
    

    在这里插入图片描述

    展开全文
  • 通过结构体地址来换算成员的偏移量 例有如下结构体 typedef struct { char bFileName[6]; //头文件名 char isInitialization; //初始化标志 uint16_t saveindex; //存储索引 从0开始每条19个字节...
  • 转载:根据结构体成员变量的地址得到结构体起始地址_我的梦-CSDN博客_结构体变量的地址 重点: (unsigned long)(&((type*)0)->...结构体中某元素的绝对地址-它的偏移量=结构体的起始地址。 ...

    转载:根据结构体成员变量的地址得到结构体起始地址_我的梦-CSDN博客_结构体变量的地址

    重点:

    (unsigned long)(&((type*)0)->member))) 通过强制转换获取元素的偏移量,其中强制转换0获取到的位置是相对位置。而结构体的具体起始地址是要获取绝对地址。先获取偏移量,再采用

    结构体中某元素的绝对地址-它的偏移量=结构体的起始地址

     

    展开全文
  • C中结构体地址偏移

    2020-08-04 09:38:50
    #define _CRT_SECURE_NO_WARNINGS #include #include #include typedef struct AdvTeacher { char name[64];... // & (t1.age) 绝对零地址偏移量 int offsize2 = (int )&(((AdvTeacher *)0)->age ); 测试结果
    #define  _CRT_SECURE_NO_WARNINGS 
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    typedef struct AdvTeacher
    {
    	char name[64]; //64
    	int age ;  //4
    	int p; //4
    	char *pname2;
    
    }AdvTeacher;
    
    int main(int argc, const char * argv [])
    {
    	int i = 0;
    	AdvTeacher  t1; // & (t1.age)
    	AdvTeacher *p = NULL;
    	p = &t1;
        
    	{
    		int offsize1 =   (int)&(p->age) - (int)p; // & (t1.age)
    		int offsize2 = (int )&(((AdvTeacher *)0)->age );
    		printf("offsize1:%d \n", offsize1);
    		printf("offsize2:%d \n", offsize2);
    
    	}
        
    	return 0;
    }
    
    
    

    相对起始地址的偏移量

    int offsize1 = (int)&(p->age) - (int)p; // & (t1.age)

    绝对零地址的偏移量

    int offsize2 = (int )&(((AdvTeacher *)0)->age );

    测试结果

    在这里插入图片描述

    展开全文
  • 利用结构体成员偏移量结构体成员地址结构体地址 1. 前言 在实际项目开发中,发现了两个有意思的宏定义。 #define offsetof(type, member) ((unsigned long)(&((type *)0)->member)) #define LIST_ENTRY...
  • #define my_offerset(type , exp) ((int)&...//然后该指针又指向该结构体某一成员地址,再由前面强转为int //则该宏就可以计算出结构体成员的偏移 一段例子 方便理解: #include <stdio.h> ..
  • https://blog.csdn.net/baidu_35679960/article/details/81538658
  • 结构体中的所有成员其首地址偏移量必须为器数据类型长度的整数被,其中第一个成员的首地址偏移量为0, 例如,若第二个成员类型为int,则其首地址偏移量必须为4的倍数,否则就要“首部填充”;以此类推 b.结构体所占...
  • c语言结构体偏移 示例1 我们先来定义一下需求: 已知结构体类型定义如下: struct node_t{ char a; int b; int c; }; 且结构体1Byte对齐 #pragma pack(1) 求: 结构体struct node_t中成员变量c的偏移。 注:...
  • 结构体成员变量偏移量

    千次阅读 2018-07-05 19:15:36
    转自示例1我们先来定义一下需求:已知结构体类型定义如下:struct node_t{ ...注:这里的偏移量指的是相对于结构体起始位置的偏移量。有三种方法:1.使用宏offsetof()。 2.定义一个结构体,【用结构体成员的地址】...
  • Q1:什么是偏移量? A:结构体变量中成员的...可知:第一个成员的偏移量为0,最后一个成员的偏移量加上最后一个成员的大小却不一定等于结构体大小(先卖个关子=。。=)。 Q2:什么是地址对齐? A:结构体成员是按...
  • #include #include struct Person { char a; int b; ... printf("Person结构体中的b的值是:%d\n",*((int*)((char *)&p2+offset1+offset2))); } int main(void) { test01(); return 0; }
  • 第二步,用(char *)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。 那这个宏到底是用来干嘛的呢?我们先来看看它在内核中是怎样定义的。 呵呵,乍一...
  • 结构体偏移量

    2022-05-20 17:16:37
    也可以通过地址的相加运算 计算偏移量 结构体嵌套结构体 #include <stddef.h> struct Person { char a; // 0 ~ 3 int b; // 4 ~ 7 }; void test01() { struct Person p1; struct Person * p = &...
  • 一 方式1:采用offsetof宏 #include #include struct PP { char a; int b; }; int main() { struct PP pp; printf("%zd\n", offsetof(struct PP, b));...但此方法不能保证可移植性,也不能对位域取偏移量
  • 获取成员的偏移量大小的方式
  • 通过宏定义求结构体变量的偏移量 typedef unsigned int uint32; #define OFFSETOF(type,field) ((uint32)&((type*)0)->field) 语句 解释 (type*)0 把地址为0的指针指向type类型的结构体 ((type*)0...
  • 假设 假设结构体变量的初始位置为 0x00 由右边 可以看出,地址相对初始0的大小就是偏移量 ​ 3.计算 a b c 的地址就为对应的偏移量 0xa - 0x00 0xc - 0x00 0xd - 0x00 4.代码实现 宏 #include #include struct S...
  • 求其成员的地址相对于整个结构体成员的偏移量。 方法: (int)(&((struct Test*)0)->member)); struct Test是结构体类型,member就是结构体的成员。 下面是测试代码。 v#include <stdio.h> #include <...
  • 利用成员变量的地址结构体地址
  • gdb输出结构体成员的偏移量

    千次阅读 2020-03-04 17:11:56
    目前在项目中做功能时,发现一个结构体异常的大,不到30k,我想找到这个结构中的那个元素比较占用空间,于是想起gdb可以出场了,但是没有按照预期的过程进行,听我慢慢道来。 需求 存在如下结构体 struct A{ int a;...
  • c语言取结构体偏移量
  • 一、指针运算 与 指针内存操作、 二、结构体偏移量计算
  • 个人博客 所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。...我在做嵌入式工作时,在已知要获取信息的 flash 地址时,需要取出相对应的信息元素,这个时候时常需要知道结构体相对于已知地址偏移,方便快.
  •   获得结构体成员偏移量的方法可以参照博客:   https://blog.csdn.net/zhanshen2015/article/details/51500757 现在主要以第二种方法(通过宏函数计算结构体成员偏移量)为例,做简单整...
  • 计算结构体偏移量

    2021-09-30 10:24:04
    C 库宏offsetof(type, member-designator)会生成一个类型为size_t的整型常量,它是一个结构成员相对于结构开头的字节偏移量。成员是由 member-designator 给定的,结构的名称是在 type 中给定的。 下面是 offsetof...
  • 在linux下进行C编程,有时候会绵连结构体的大小问题。结构体大小并不等于其内部所有成员大小之和,这个主要是由于结构体需要...所有如果想在程序中基于偏移量来获取结构体成员的值时,靠人工计算该成员相对于结构体首

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 50,840
精华内容 20,336
热门标签
关键字:

结构体首地址的偏移量