C语言提高0——结构体是一种自定义数据类型

结构体数据类型

结构体变量

结构体指针

结构体数组

结构体作函数参数

结构体嵌套一级指针(未完全搞懂)

结构体嵌套二级指针(未学)

结构体中的深拷贝与浅拷贝

结构体中的偏移量

 

结构体

是一种构造数据类型,它把不同类型的数据组合成一个整体,来自定义数据类型

 

我们都知道在数据类型中,char类型占1个字节,short占2个字节,int占4个字节,long占8个字节等等。

在计算结构体大小时需要考虑其内存布局,结构体在内存中存放是按单元存放的,每个单元多大取决于结构体中最大基本类型的大小

 https://www.cnblogs.com/kl2blog/p/6908048.html

 

 一、结构体类型定义与结构体变量定义

1、常用的两种写法(定义类型,用类型去定义变量):

  第一种:

//类型定义
struct teacher
{
    char name[12];
    int age;
    int id;
};
void main()
{
   //变量定义并初始化 
   struct  teacher t1 = {"a",32,02};
}

  第二种:用typedef

typedef struct teacher1
{
    char name[12];
    int age;
    int id;
}teacher1;
void main() { teacher1 t2 = {"a",32,02}; }

2、结构体变量定义与初始化的三种方法(了解其余两种)

  第二种:定义类型的同时,定义变量(可以同时初始化,而且初始化只能在这里进行)

struct teacher
{
    char name[12];
    int age;
    int id;
}t1,t2={“b”,23,02};

  第三种:不带结构体名的

struct 
{
    char name[12];
    int age;
    int id;
}t1,t2={“b”,23,02};

3、操作结构体(内存空间)的两种方法

第一种:变量法   t1.

teacher1 t2 = {"a",32,02};
printf("%d\n", t2.age);
t2.age = 22;
printf("%d\n", t2.age);

t1..号是寻址操作 计算age 相对于 t1大变量的 偏移量 ===》计算 cup中进行。没有操作内存,=号才是操作内存。

第二种:指针法

teacher1* p = NULL;
p = &t2;
p->age = 12;
printf("%d\n", p->age);
strcpy(p->name, "t1name");
printf("t2.name:%s \n", p->name);

p->  是寻址操作 算age 相对于 t2大变量的偏移量 ,计算 cup中进行。

 

二、结构体变量作函数参数 pk 结构体指针作函数参数(结构体内存四区模型)

1、=号操作下 编译器的行为

 

Teacher  t1 = {"aaaa", 32, 02};
Teacher  t2;

t2 = t1; //=号操作下 编译器的行为

//编译器给我们提供 简单 =号 赋值操作 。。。我们要顺从
printf("t2.name:%s \n", t2.name);
printf("t2.age:%d \n", t2.age);
printf("t2.id:%d \n", t2.id);

2、结构体变量作函数参数 pk 结构体指针作函数参数,到底哪个正确?

//结构体变量作函数参数
void  copyTeacher(Teacher to, Teacher from )
{
    to = from;    
}
//结构体指针作函数参数
void  copyTeacher02(Teacher *to, Teacher *from )
{
    //(*to) = (*from);
    *to = *from;
}
void main()
{
    Teacher  t1 = {"aaaa", 32, 02};
    Teacher  t3;

    copyTeacher02(&t3, &t1);
    printf("t3.name:%s \n", t3.name);
    printf("t3.age:%d \n", t3.age);
    
    system("pause");
}

3、内存四区模型:

 

 三、结构体作函数参数应用+结构体数组

1、定义一个结构体数组,输入年龄,排序

typedef struct teacher
{
    char name[12];
    int age;
    int id;
}teacher;
void printTeacher(teacher* array,int num)
{
    int i;
    for (i = 0; i < num; i++)
    {

        printf("%d\n", array[i].age);
    }
}
void sortTeacher(teacher* array, int num)
{
    int i, j;
    for (i = 0; i < num; i++)
    {
        for (j = 0; j < num - 1; j++)
        {
            if (array[j].age >array[j + 1].age)
            {
                teacher temp=array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }
}
void main()
{
    teacher tArray[3];//结构体数组
    int i;

    for (i = 0; i < 3; i++)
    {
        printf("请输入三位老师年龄:");
        scanf("%d", &tArray[i].age);
    }
    sortTeacher(tArray, 3);
    printTeacher(tArray, 3);
    system("pause");
}

2、在堆上开辟内存代替结构体数组

teacher* createTeacher(int num)
{
    teacher* array = NULL;
    array=(teacher*)malloc(sizeof(teacher)*num);

    if (array==NULL)
    {
        return NULL;
    }
    return array;
}
void freeTeacher(teacher*p)
{
    if (p != NULL)
    {
        free(p);
    }
}
void main()
{
    int i;
    int num = 3;
    teacher* pArray = NULL;
    pArray = createTeacher(num);
    for (i = 0; i < 3; i++)
    {
        printf("请输入三位老师年龄:");
        scanf("%d", &tArray[i].age);
    }
    sortTeacher(pArray, 3);
    printTeacher(pArray, 3);

    system("pause");
}

 “free(p)”释放的是指针变量 p 所指向的内存,而不是指针变量 p 本身。指针变量 p 并没有被释放,仍然指向原来的存储空间。所以一定要记住一条:free(p) 完之后,一定要将指针变量 p 置为 NULL。

其实它就做了一件事:斩断指针变量与这块内存的关系。

https://www.cnblogs.com/chunzhulovefeiyue/p/6821317.html

四、结构体嵌套一级指针

注意的点:没有内存,哪来的指针!

typedef struct teacher
{
    char name[12];
    char* alisname;//定义了指针变量,但并没有指向内存空间
    int age;
    int id;
}teacher;
void main()
{
    printf("\nplease enter alisname:");
    scanf("%d", (pArray[i].alisname));//向指针所指的内存空间copy数据
}

error!需要向指针赋值,让指针指向一块内存空间!malloc

 

teacher* createTeacher2(int num)
{
    int i;
    teacher* array = NULL;
    array = (teacher*)malloc(sizeof(teacher)*num);
    memset(array, 0, sizeof(teacher)* num);//初始化内存
    if (array == NULL)
    {
        return NULL;
    }
    for (i = 0; i < num; i++)
    {
        array[i].alisname = (char*)malloc(60);
    }
    return array;
}
void FreeTeacher(teacher *p, int num)
{
    int    i = 0;
    if (p == NULL)
    {
        return;
    }
    for (i = 0; i<num; i++)
    {
        if (p[i].alisname != NULL)
        {
            free(p[i].alisname);
        }
    }
    free(p);
}
void main()
{
    int i;
    int num = 3;
    teacher* pArray = NULL;
    //pArray = createTeacher(num);
    pArray = createTeacher2(num);

    for (i = 0; i<num; i++)
    {
        printf("\nplease enter alisname:");
        scanf("%d", (pArray[i].alisname));
    }
    for (i = 0; i < num; i++)
    {

        printf("%d\n", *(pArray[i].alisname));
    }
    system("pause");
}

 五、结构体中嵌套二级指针

六、结构体中的深拷贝与浅拷贝

问题出现在结构体中嵌套一个一级指针,然后把结构体变量1复制到变量2中,一级指针只会把地址复制,而不会重新申请一块内存

解决办法:手动申请内存,并将内存空间的值copy过去

typedef struct teacher
{
    char name[12];
    char* pname2;
    int age;
    
}teacher;
//编译器的=号操作,只会把指针变量的值,从from  copy 到 to,但 
//不会 把指针变量 所指 的 内存空间 给copy过去..//浅copy

//结构体中套一个 1级指针 或 二级指针 

//如果 想执行深copy,再显示的分配内存
void copyTeacher(teacher *to, teacher *from)
{
    *to = *from;
    //以下两步是深拷贝内容:不添加该程序会卡死
    to->pname2 = (char*)malloc(100);
    *(to->pname2) = *(from->pname2);
}
void main()
{
    teacher t1, t2;
    strcpy(t1.name, "name1");
    t1.pname2 = (char*)malloc(100);//先分配内存
    strcpy(t1.pname2,"sss");
    //t1 copy t2
    copyTeacher(&t2, &t1);

    if (t1.pname2 != NULL)
    {
        free(t1.pname2);
        t1.pname2 = NULL;
    }
    if (t2.pname2 != NULL)
    {
        free(t2.pname2);
        t2.pname2 = NULL;
    }
    system("pause");
}

 

七、结构体中的偏移量

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

 

posted @ 2019-05-20 16:56  zr-zhang2019  阅读(660)  评论(0)    收藏  举报