精华内容
下载资源
问答
  • 结构体偏移量
    2022-05-20 17:16:37

    1. 可以利用offsetof来计算结构体中属性的偏移
    2. 也可以通过地址的相加运算  计算偏移量
    3. 结构体嵌套结构体
    #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  );
    }

    更多相关内容
  • 一、结构体成员偏移量、 二、完整代码示例





    一、结构体成员偏移量



    获取 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
    请按任意键继续. . .
    

    在这里插入图片描述

    展开全文
  • 一、先来一段理论知识 ANSI C标准允许任何值为0的常量被强制转换成任何一种类型的指针,并且转换结果是一个...m)的意图并非想存取s字段内容,而仅仅是计算当结构体实例的首址为((s*)0)时m字段的地址。聪明的编译器...
         一、先来一段理论知识

            ANSI C标准允许任何值为0的常量被强制转换成任何一种类型的指针,并且转换结果是一个NULL指针,因此((s*)0)的结果就是一个类型为s*的NULL指针。如果利用这个NULL指针来访问s的成员当然是非法的,但&(((s*)0)->m)的意图并非想存取s字段内容,而仅仅是计算当结构体实例的首址为((s*)0)时m字段的地址。聪明的编译器根本就不生成访问m的代码,而仅仅是根据s的内存布局和结构体实例首址在编译期计算这个(常量)地址,这样就完全避免了通过NULL指针访问内存的问题。

            二、在实践中检验理论

            下面是我在window环境下VS2008编译器下的记录,

           

    1. #include <stdlib.h>  
    2. #include <iostream>  
    3. using namespace std;  
    4.   
    5. typedef struct ISO_MSG  
    6. {  
    7.     char    msg_type[5];  
    8.     char    proc_code[7];  
    9. }ISO_MSG;  
    10.   
    11. #define fld_sizeof(s, m) sizeof(((s *)0)->m)  
    12. //#define offsetof(s,m) (( (size_t) &( ( (s*)0 )->m )) - (size_t)((s*)0))  
    13. #define offsetof1(s,m) ( (size_t) &( ( (s*)0 )->m ))  
    14.   
    15. int _tmain(int argc, _TCHAR* argv[])  
    16. {  
    17.     ISO_MSG sIsoMsg;  
    18.     memset((void*)&sIsoMsg,0,sizeof(ISO_MSG));  
    19.   
    20.     strcpy(sIsoMsg.msg_type,"0200");  
    21.     strcpy(sIsoMsg.proc_code,"000000");  
    22.   
    23.     cout << fld_sizeof(ISO_MSG,msg_type) << offsetof1(ISO_MSG,msg_type) << endl;  
    24.     cout << fld_sizeof(ISO_MSG,proc_code) << offsetof1(ISO_MSG,proc_code) << endl;  
    25.   
    26.     system("pause");  
    27.     return 0;  
    28. }  
    #include <stdlib.h>
    #include <iostream>
    using namespace std;
    
    typedef struct ISO_MSG
    {
    	char	msg_type[5];
    	char	proc_code[7];
    }ISO_MSG;
    
    #define fld_sizeof(s, m) sizeof(((s *)0)->m)
    //#define offsetof(s,m) (( (size_t) &( ( (s*)0 )->m )) - (size_t)((s*)0))
    #define offsetof1(s,m) ( (size_t) &( ( (s*)0 )->m ))
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	ISO_MSG sIsoMsg;
    	memset((void*)&sIsoMsg,0,sizeof(ISO_MSG));
    
    	strcpy(sIsoMsg.msg_type,"0200");
    	strcpy(sIsoMsg.proc_code,"000000");
    
    	cout << fld_sizeof(ISO_MSG,msg_type) << offsetof1(ISO_MSG,msg_type) << endl;
    	cout << fld_sizeof(ISO_MSG,proc_code) << offsetof1(ISO_MSG,proc_code) << endl;
    
    	system("pause");
    	return 0;
    }

             在上例中,存在两个宏定义,fld_sizeof和offsetof;这两个宏定义一个是计算结构成员变量字节大小,一个是计算偏移量,其中offsetof和offsetof1是等价的,

            三、系统的offsetof定义

             该宏在Linux内核代码(版本2.6.22)中定义如下:
             /* Offset of member MEMBER in a struct of type TYPE. */
            #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)


                在windows下,

               

    1. #ifdef  _WIN64  
    2. #define offsetof(s,m)   (size_t)( (ptrdiff_t)&reinterpret_cast<const volatile char&>((((s *)0)->m)) )  
    3. #else  
    4. #define offsetof(s,m)   (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))  
    5. #endif  
    6.   
    7. #else  
    8.   
    9. #ifdef  _WIN64  
    10. #define offsetof(s,m)   (size_t)( (ptrdiff_t)&(((s *)0)->m) )  
    11. #else  
    12. #define offsetof(s,m)   (size_t)&(((s *)0)->m)  
    13. #endif  
    #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)
    #endif
             四、参考内容

             http://www.jxva.com/blog/201202/335.html,这里有非常详细的说明,大家可以来这里查看。

    展开全文
  • 文章目录一、结构体基本使用二、结构体常见赋值问题及解决三、结构体与一级指针嵌套四、结构体与二级指针嵌套五、结构体偏移量六、内存对齐问题 一、结构体基本使用 基本规则与使用方法: 1.正常结构体定义时不能赋...

    文章可能比较长,如果想仔细了解结构体知识的话请大佬们耐心看完。

    一、结构体基本使用

    基本规则与使用方法:
    1.正常结构体定义时不能赋初值;

    struct Person
    {
    	char name[64];
    	//int age = 50;//定义时不能赋初值,只有使用变量时才赋初值。
    	int age;
    };
    

    2.使用typedef对结构体取别名;

    typedef struct Person
    {
    	char name[64];
    	int age;
    }MyPerson;//MyPerson为struct Person类型的别名;
    
    void test()
    {
    	MyPerson p = {"aaa",10};//可以直接用别名使用;
    }
    

    3.没有写时typedef是定义了一个结构体变量(与上面对比),可以对其直接使用;

    struct Person
    {
    	char name[64];
    	int age;
    }MyPerson = {"小米",200};//定义了一个结构体变量,可以直接使用
    
    void test()
    {
    	printf("姓名:%s 年龄:%d\n",MyPerson.name,MyPerson.age);
    }
    

    输出结果:
    在这里插入图片描述
    4.匿名类型下创建一个结构体变量,只有一个MyPerson3结构体变量可以使用,无法创建新的变量,也可对其直接使用;局限性强,基本不会使用。

    struct
    {
    	char name[64];
    	int age;
    }MyPerson3 = {"小白",30};
    
    void test()
    {
    	printf("姓名:%s 年龄:%d\n",MyPerson3.name,MyPerson3.age);
    }
    

    输出结果:
    在这里插入图片描述
    5.在栈区与堆区创建结构体变量;

    void test()
    {
    	//在栈上创建结构体
    	struct Person p1 = {"aaa",10};
    
    	//在堆区创建结构体变量
    	struct Person* p2 = (struct Person*)malloc(sizeof(struct Person));
    	p2->age = 66;
    	strcpy(p2->name,"bbb");
    }
    

    6.在栈上与堆上创建结构体变量数组;

    typedef struct Person
    {
    	char name[64];
    	int age;
    }MyPerson;
    
    void PrintArray(struct Person persons[],int len)
    {
    	for (int i=0; i<len; i++)
    	{
    		printf("姓名:%s  年龄:%d\n",persons[i].name,persons[i].age);
    	}
    }
    
    void test()
    {
    	//在栈上创建结构体变量数组
    	struct Person persons[] = 
    	{
    		{"aaa",10},
    		{"bbb",20},
    		{"ccc",30},
    		{"ddd",40}
    	};
    	int len = sizeof(persons)/sizeof(struct Person);
    	PrintArray(persons,len);
    
    	//在堆区创建结构体变量数组
    	struct Person* personArr = (struct Person*)malloc(sizeof(struct Person)*4);
    	for (int i=0; i<4; i++)
    	{
    		sprintf(personArr[i].name,"name_%d",i);
    		personArr[i].age = i+18;
    	}
    	PrintArray(personArr,4);
    
    	if (personArr != NULL)
    	{
    		free(personArr);
    		personArr = NULL;
    	}
    }
    

    打印结果:输出成功。
    在这里插入图片描述

    二、结构体常见赋值问题及解决

    结构体常见赋值问题以及解决:
    1.结构体变量赋值问题:在栈上开辟内存 : 将p2赋值给了p1

    struct Person
    {
    	char name[64];
    	int age;
    };
    
    void test()
    {
    	struct Person p1 = {"Tom",20};
    	struct Person p2 = {"Jerry",18};
    
    	p1 = p2;//将p2赋值给p1
    
    	printf("p1的姓名:%s p1的年龄:%d\n",p1.name,p1.age);
    	printf("p2的姓名:%s p2的年龄:%d\n",p2.name,p2.age);
    }
    

    那么系统做了什么操作呢?
    系统提供了浅拷贝操作,将p2每个字节拷贝到p1上,拷贝成功。

    在这里插入图片描述
    输出结果:赋值成功;
    在这里插入图片描述
    2.结构体变量赋值问题:在堆区开辟内存(浅拷贝出现的问题) :
    若将上面代码改为如下代码:

    struct Person2
    {
    	char* name;
    	int age;
    };
    
    void test2()
    {
    	struct Person2 p1;
    	p1.age = 18;
    	p1.name = (char*)malloc(sizeof(char)*64);
    	strcpy(p1.name,"Tom");
    
    	struct Person2 p2;
    	p2.age = 20;
    	p2.name = (char*)malloc(sizeof(char)*128);
    	strcpy(p2.name,"Jerry");
    
    	printf("p1的姓名:%s p1的年龄:%d\n",p1.name,p1.age);
    	printf("p2的姓名:%s p2的年龄:%d\n",p2.name,p2.age);
    }
    

    先打印一下,打印成功。
    在这里插入图片描述
    此时,我们再将p2赋值给p1。

    p1 = p2;//p2赋值给p1
    

    再打印一下:还是没问题的
    在这里插入图片描述
    但是我们此时是在堆区开辟的内存,需要手动释放(堆区才会出现的问题,栈区不会出现该问题),我们执行如下代码后。

    	if (p1.name != NULL)
    	{
    		free(p1.name);
    		p1.name = NULL;
    	}
    
    	if (p2.name != NULL)
    	{
    		free(p2.name);
    		p2.name = NULL;
    	}
    

    程序崩溃!未响应,关了半天才关掉!
    在这里插入图片描述
    为什么会发生这样的结果呢?我们来研究一下:
    在这里插入图片描述
    那么如何解决它呢?
    C语言里面解决它的方案:手动做一个赋值操作。开辟新的空间,最后释放。
    在这里插入图片描述
    代码操作:先将p1释放干净,重新手动开辟一块新的空间,手动使用strcpy赋值,最后再释放。

        struct Person2
    {
    	char* name;
    	int age;
    };
    
    void test2()
    {
    	struct Person2 p1;
    	p1.age = 18;
    	p1.name = (char*)malloc(sizeof(char)*64);
    	strcpy(p1.name,"Tom");
    
    	struct Person2 p2;
    	p2.age = 20;
    	p2.name = (char*)malloc(sizeof(char)*128);
    	strcpy(p2.name,"Jerry");
    
    	//p1 = p2;//p2赋值给p1
    	//自己提供一个赋值操作
    	//先释放原有的内容
    	if (p1.name != NULL)
    	{
    		free(p1.name);
    		p1.name = NULL;
    	}
    	p1.name = (char*)malloc(strlen(p2.name)+1);
    	strcpy(p1.name,p2.name);
    	p1.age = p2.age;
    
    	printf("p1的姓名:%s p1的年龄:%d\n",p1.name,p1.age);
    	printf("p2的姓名:%s p2的年龄:%d\n",p2.name,p2.age);
    
    	if (p1.name != NULL)
    	{
    		free(p1.name);
    		p1.name = NULL;
    	}
    
    	if (p2.name != NULL)
    	{
    		free(p2.name);
    		p2.name = NULL;
    	}
    }
    

    输出一下:打印成功,也没有崩溃,堆区数据也释放干净。
    在这里插入图片描述

    三、结构体偏移量

    我们已知一个结构体:如何计算结构体中某个变量它的偏移量呢?
    方式一:口算 如下,我们明白内存对齐的方式,会自动补齐;因此a补齐为0-3,b的偏移量就是4了。

    struct Person
    {
    	char a;//0~3
    	int b;//4~7
    };
    

    方式二:利用offsetof宏
    offsetof 会生成一个类型为 size_t 的整型常量,其功能是一个结构成员相对于结构开头的字节偏移量。

    宏声明:offsetof(type, member-designator)
    参数:
    type:这是一个class类型,其中,member-designator是一个有效的成员指示器。
    member-designator:这是一个class类型的成员指示器。
    返回值:该宏返回类型为 size_t 的值,表示 type 中成员的偏移量。
    

    代码实例:

    struct Person
    {
    	char a;//0~3
    	int b;//4~7
    };
    
    void test()
    {
    	struct Person p1;
    	struct Person* p = &p1;
    	printf("b的偏移量为:%d\n",offsetof(struct Person,b));
    }
    

    可以直接计算出来偏移量:4
    在这里插入图片描述
    方式三:利用地址计算 : 利用b的地址减去a的地址

    printf("b的偏移量为:%d\n",(int)&(p->b)-(int)p);//即b的地址减去a的地址
    

    偏移量也为:4
    在这里插入图片描述
    实际案例1:通过偏移量获取结构体里面的数据

    struct Person
    {
    	char a;
    	int b;
    };
    
    void test2()
    {
    	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));
    }
    

    输出结果:
    在这里插入图片描述
    实际案例2:通过偏移量找到结构体中嵌套结构体的数据 结构体中嵌套结构体本质是将其展开。

    struct Person
    {
    	char a;
    	int b;
    };
    
    struct Person2
    {
    	char a;
    	int b;
    	struct Person c;//相当于将上面的结构体展开
    };
    
    void test()
    {
    	struct Person2 p = {'a',10,'c',20};
    
    	int offset1 = offsetof(struct Person2,c);
    	int offset2 = offsetof(struct Person,b);
    	printf("方式1访问偏移量为:%d\n",*(int*)((char*)&p+offset1+offset2));//方式1
    	printf("方式2访问偏移量为:%d\n",((struct Person*)((char*)&p+offset1))->b);//方式2
    }
    
    

    打印结果:成功找到
    在这里插入图片描述

    四、内存对齐问题

    为什么需要内存对齐?
           内存的最小单元是一个字节,当CPU从内存中读取数据的时候,是一个一个字节读取。但是实际上CPU将内存当成多个块,每次从内存中读取一个块,这个块的大小可能是2、4、8、16等。内存对齐是操作系统为了提高访问内存的策略,操作系统再访问内存的时候,每次读取一定的长度(这个长度是操作系统默认的对齐数,或者默认对齐数的整数倍)。如果没有对齐,为了访问一个变量可能产生二次访问。内存对齐的优势:以空间换时间。
    在这里插入图片描述
    那么如何进行内存对齐?
    1.对于标准数据类型,它的地址只要是它的长度的整数倍。
    2.对于非标准数据类型,如结构体,要遵循以下对齐原则:
    ①从第一个属性开始,偏移为0;
    ②从第二个属性开始,地址要放在该类型整数倍与对齐模数(系统中默认为8)比取小的值的整数倍上。
    ③所有的属性都计算完成后,整体在做二次对齐,整体需要放在属性中最大类型与对齐模数比取效地整数倍上。
    如何查看对齐模数:输入下列代码,重新生成下;对齐模数可以改为2^n;

    #pragma pack(show)//查看对齐模数,输出该代码,不要运行,重新生成以下就好了
    

    可以看到编译器最下面:
    在这里插入图片描述
    实例1:计算结构体大小

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

    输出结果:根据内存对齐为24
    在这里插入图片描述
    实例2:修改对齐模数为1(相当于没有内存对齐,挨个相加)后计算

    #pragma pack(1)
    typedef struct _STUDENT
    {
    	int a;//0-3
    	char b;//4
    	double c;//5-12
    	float d;//13-16
    }Student;
    
    void test()
    {
    	printf("sizeof = %d\n",sizeof(Student));
    }
    

    输出结果:修改对齐模数为1,挨个数据类型相加即为结果。
    在这里插入图片描述
    实例3:结构体嵌套结构体时,只需要看子结构体中最大数据类型就可以了。

    typedef struct _STUDENT
    {
    	int a;
    	char b;
    	double c;
    	float d;//总大小为24
    }Student;
    
    typedef struct _STUDENT2
    {
    	char a;//0-7
    	Student b;//8-31
    	double c;//32-39
    }Student2;
    
    void test()
    {
    	printf("sizeof = %d\n",sizeof(Student2));
    }
    

    输出结果:总大小为40字节
    在这里插入图片描述

    五、结构体与一级指针嵌套

    我们直接看一个例子来使用它:大致在堆区创建结构如下。需求为打印出来这里面所有人的年龄和姓名。
    大致流程如下:
    ①设计一个结构体struct Person{char* name,int age}
    ②在堆区创建结构体指针数组malloc(sizeof(struct Person*)*3);
    ③给每个结构体也分配到堆区
    ④给每个结构体的姓名分配到堆区
    ⑤打印数组中所有人的信息
    ⑥释放堆区数据。
    在这里插入图片描述
    实现代码:

    struct Person
    {
    	char* name;
    	int age;
    };
    
    void printArray(struct Person **pArray,int len)
    {
    	for (int i=0; i<len; i++)
    	{
    		printf("姓名:%s  年龄:%d\n",pArray[i]->name,pArray[i]->age);
    	}
    }
    
    void freeSpace(struct Person** pArray,int len)
    {
    	for (int i=0; i<len; i++)
    	{
    		if (pArray[i]->name != NULL)//释放属性
    		{
    			printf("%s被释放了\n",pArray[i]->name);
    			free(pArray[i]->name);
    			pArray[i]->name = NULL;
    		}
    
    		free(pArray[i]);//释放结构体
    		pArray[i] = NULL;
    	}
    	free(pArray);//释放数组
    	pArray = NULL;
    }
    
    struct Person** allocateSpace()
    {
    	struct Person** pArray = (struct Person**)malloc(sizeof(struct Person*)*3);//分配空间
    	for (int i=0; i<3; i++)
    	{
    		//给每个结构体开辟内存
    		pArray[i] = (struct Person*)malloc(sizeof(struct Person));
    
    		//给每个结构体的姓名开辟内存
    		pArray[i]->name = (char*)malloc(sizeof(char)*64);
    		sprintf(pArray[i]->name,"name_%d",i+1);
    		pArray[i]->age = i+20;
    	}
    	return pArray;
    }
    
    void test()
    {
    	struct Person** pArray = NULL;//利用被调函数分配内存
    
    	pArray = allocateSpace();
    	printArray(pArray,3);
    	freeSpace(pArray,3);
    	pArray = NULL;
    }
    

    输出结果:成功实现结构体与一级指针嵌套使用。
    在这里插入图片描述

    六、结构体与二级指针嵌套

    我们直接看一个例子来使用它:
    在这里插入图片描述
    代码实现:

    struct Teacher
    {
    	char* name;
    	char** Students;
    };
    
    void allocateSpace(struct Teacher*** teachers)//分配内存
    {
    	struct Teacher** pArray = (struct Teacher**)malloc(sizeof(struct Teacher*)*3);
    
    	for (int i=0; i<3; i++)
    	{
    		//给每个老师分配空间
    		pArray[i] = (struct Teacher*)malloc(sizeof(struct Teacher));
    
    		//给每个老师姓名分配空间
    		pArray[i]->name = (char*)malloc(sizeof(char)*64);
    		sprintf(pArray[i]->name,"Teacher_%d",i+1);
    
    		//给老师带的学生数组分配空间
    		pArray[i]->Students = (char**)malloc(sizeof(char*)*4);//学生数组
    		//给4个学生再分配内存再赋值
    		for (int j=0; j<4; j++)
    		{
    			pArray[i]->Students[j] = (char*)malloc(sizeof(char)*64);
    			sprintf(pArray[i]->Students[j],"%s_Student_%d",pArray[i]->name,j+1);
    		}
    	}
    	*teachers = pArray;
    }
    
    void ShowArray(struct Teacher** pArray,int len)
    {
    	for (int i=0; i<len; i++)
    	{
    		printf("%s\n",pArray[i]->name);
    		for (int j=0; j<4; j++)
    		{
    			printf("     %s\n",pArray[i]->Students[j]);
    		}
    	}
    }
    
    void freeSpace(struct Teacher** pArray,int len)
    {
    	for (int i=0; i<len; i++)
    	{
    		if (pArray[i]->name != NULL)//释放老师的姓名
    		{
    			free(pArray[i]->name);
    			pArray[i]->name = NULL;
    		}
    		
    		for (int j=0; j<4; j++)//释放每个学生
    		{
    			if (pArray[i]->Students[j] != NULL)
    			{
    				free(pArray[i]->Students[j]);
    				pArray[i]->Students[j] = NULL;
    			}
    		}
    		//释放学生数组
    		free(pArray[i]->Students);
    		pArray[i]->Students = NULL;
    
    		//释放老师
    		free(pArray[i]);
    		pArray[i] = NULL;
    	}
    	//释放老师数组
    	free(pArray);
    	pArray = NULL;
    }
    
    void test()
    {
    	struct Teacher** pArray = NULL;
    	allocateSpace(&pArray);//分配内存
    	ShowArray(pArray,3);//打印数组
    	freeSpace(pArray,3);//释放
    	pArray = NULL;
    }
    

    打印结果:成功实现结构体与一级指针嵌套使用。
    在这里插入图片描述

    展开全文
  • c语言结构体偏移 示例1 我们先来定义一下需求: 已知结构体类型定义如下: struct node_t{ char a; int b; int c; }; 且结构体1Byte对齐 #pragma pack(1) 求: 结构体struct node_t中成员变量c的偏移。 注:...
  • c语言取结构体偏移量
  • C语言计算结构体成员偏移量 在一些面试题中见到了类似的题目,现在进行总结。(这个正式冷门的知识点,正常开发中几乎没有遇到过) 描述: 对于几个结构体, 求其成员的地址相对于整个结构体成员的偏移量。 方法: ...
  • 01内存对齐之结构体偏移量 前提概念 结构体偏移量:所谓偏移量,就是我们每个结构体成员的首地址而已。 1 求结构体成员偏移量的两中办法 1)简单求结构体成员偏移量 。 // 注意:求偏移量时,必须将地址转成int整数...
  • c语言——结构体偏移

    千次阅读 2020-05-18 17:26:59
    目录c语言——结构体偏移整数类型浮点类型例子结构体成员偏移量test01test02test03参考资料 c语言——结构体偏移 学习结构体偏移前,我们先复习一下c语言的数据类型 整数类型 下表列出了关于标准整数类型的存储大小...
  • 个人博客 所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。...我在做嵌入式工作时,在已知要获取信息的 flash 地址时,需要取出相对应的信息元素,这个时候时常需要知道结构体相对于已知地址的偏移,方便快.
  • stddef.h下的offset计算结构体属性相对结构体首地址偏移量 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include<stddef.h>//offsetof...
  • C语言结构体成员偏移量的计算

    千次阅读 2019-04-11 15:29:52
    请参考... 计算方式: 1. 使用宏函数: #include <stddef.h> ... size_t offsetof(type, member);...2. 自己计算偏移(B-A形式) 测试代码如下: #include <stdi...
  • 1、结构体偏移量和大小计算: https://www.cnblogs.com/qiumingcheng/p/11370836.html 2、结构体的初始化: https://www.cnblogs.com/lvmf/p/10927446.html 3、memset函数用法: ... ...
  • 结构体偏移量计算

    千次阅读 2016-05-07 20:44:55
    #include using namespace std; #define FIND(struc,e) (size_t)&(((struc*)0)->e) ... //b的偏移量是4,因为a的偏移量是0,b的偏移量是a的偏移量加上a的类型的大小算出来的,a是int型的,所以a要占4个字
  • 结构体偏移量

    千次阅读 2016-08-18 17:56:27
    根据C语言的结构体内存对齐规则,Teacher这个结构体含有72个字节,现在来测试age相对这个结构体偏移量,#define _CRT_SECURE_NO_WARNINGS #include #include #include <string.h>//结构体类型定义下来,内部的成员...
  • 计算结构体成员偏移量

    千次阅读 2018-10-23 14:57:29
    写一个宏计算出结构体成员的偏移量。  假设有如下一个结构体,要计算成员c的在结构体中的偏移量。 typedef struct Type_t{  char a; // 0  int b; // 4~7  double c; // 8~16 }; 注意,上述的结构体必须考虑...
  • 文章目录1 不同类型指针的步长2 结构体成员偏移量 1 不同类型指针的步长 (1)不同类型的指针 +1 时,内存偏移的字节数不同。 char *类型指针 + 1,内存偏移 1 字节; int *类型指针 + 1,内存偏移 4 字节; ...
  • 在使用C语言对STM32编程的过程中,经常使用到结构体,本文介绍了一种得到结构体中一个field的偏移量的方法。
  • 第二步,用(char *)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。 那这个宏到底是用来干嘛的呢?我们先来看看它在内核中是怎样定义的。 呵呵,乍一...
  • C/C++获取结构体中变量的偏移量 1.某些特殊需求下,我们需要知道某个变量在其结构体中的偏移位置。 通常的做法就是定义一个宏变量,如下: #define OFFSET(structure, member) ((int64_t)&((structure*)0)->...
  • 不定义结构体变量,如何计算结构体成员的相对偏移量?如何判断是大端存放,还是小段存放?方法一:字符指针判断方法二:联合体判断 对齐规则(三条) 结构体变量的首地址,必须是结构体变量中“最大基本数据类型...
  • 结构体成员变量偏移量

    千次阅读 2018-07-05 19:15:36
    转自示例1我们先来定义一下需求:已知结构体类型定义如下:struct node_t{ ...注:这里的偏移量指的是相对于结构体起始位置的偏移量。有三种方法:1.使用宏offsetof()。 2.定义一个结构体,【用结构体成员的地址】...
  • 把这个地址强制转换成 size_t 类型,就相当于结构体成员相对于首地址的偏移量 #define Offset(type ,exp) ((int)(&((type*)0)->exp)) struct Student {  char s_id[10];  char s_name[10];  char s_...
  • 则通过&(((DeviceInfoDetailTable_Typedef *)0) -> extAddr),就得到了元素extAddr的地址,由于基址为0,所以偏移量被计算出来。 类似的可以使用宏来使用计算偏移量: #define STRUCT_OFFSET(id, element...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 50,918
精华内容 20,367
关键字:

结构体偏移量

友情链接: digital-human.zip