结构体做函数参数

一、目录:

《1》结构体基础知识:
<1>结构体类型定义及结构体变量定义
<2>结构体变量的引用
<3>结构体变量指针

《2》结构体知识进阶
<1>结构体做函数参数
<2>结构体数组
<3>案例
从键盘获取数据,给结构体变量初始化,并且排序,打印结构体

《3》工程开发中,结构体应用常见的模型及典型的错误用法
<1>结构体嵌套一级指针
<2>结构体嵌套二级指针
<3>深拷贝与浅拷贝

二、具体展开

《1》结构体基础知识:

<1>结构体类型定义及结构体变量定义

//结构体类型定义:固定大小空间的内存块
struct teacher
{
    char name[62];//64
    int age;//4
    //在32位编译环境下,默认4字节对齐
}

void main()
{
    //结构体变量的定义及初始化
    struct teacher t1={"daiwen",22};
    system("pause");
}
//在c编译环境下和.cpp环境下变量定义方法有所区别
struct teacher t1;//C语言需要加上struct关键字
teacher t2;//C++中则不必

<2>结构体变量的引用

struct teacher
{
    char name[64];
    int age;
}
    struct teacher t1;

<3>结构体变量指针
struct teacher *p1=NULL;

p1->age=10;
《2》结构体知识进阶

<1>结构体做函数参数

#include
#include
#include
struct teacher
{
    char name[64];//64
    int age ; //4
};
//形参改变,对实参没有影响
//形参是函数在临时区开辟的空间,随着函数的结束,空间将跟着销毁
void copy01(struct teacher from,struct teacher to)//用结构体变量作形参
{
    memcpy(&to, &from,sizeof(struct teacher));
}

//形参和实参指向同一块地址空间,通过形参来改变实参,这正是指针的精华所在
//采用结构体指针变量作形参
void copy02(struct teacher* from,struct teacher* to)
{
    memcpy(to, from,sizeof(struct teacher));
}
void main()
{
    struct teacher t1={"dddd",23};
    struct teacher t2={"t2",24};
    struct teacher *p=NULL;
    //copy01(t1,t2);
    copy02(&t1,&t2);

    printf("%s",t2.name );
    printf("%s",p->name );
    system("pause");
}

结构体做函数参数_第1张图片
函数调用过程内存图
结构体做函数参数_第2张图片

<2>结构体数组
结构体类型是复杂的数据类型,结构体指针一出来就是一级指针

struct teacher tarray[10];
tarray[0].age=11;//.为成员操作符

<3>案例

从键盘获取数据,给结构体变量初始化,并且排序,打印结构体

#include
#include
#include

struct Teacher //结构体
{
    char name[62];
    int age;
};
int printarray(struct Teacher *array,int num)//打印函数
{
    int i=0;
    for(i=0;iprintf("%d ",array[i].age);
    }
    return 0;
}

int sortarray(struct Teacher *tarray,int num )//排序函数
{
    int i=0,j=0;
    struct Teacher tmp;
    for(i=0;i//选择排序法
    {
        for(j=i+1;jif(tarray[i].agereturn 0;
}

int  main()
{
    int i=0;
    struct Teacher tarray[10];

    for(i=0;i<4;i++)
    {
        printf("请输入age:\n");
        scanf("%d",&tarray[i].age);
    }
    printf("排序之前:\n");
    printarray(tarray,4);

    printf("\n排序之后 \n");
    sortarray(tarray,4);
    printarray(tarray,4);
    return 0;
}

结构体做函数参数_第3张图片

《3》工程开发中,结构体应用常见的模型及典型的错误用法

在工程开发中,切忌将同一块空间进行重复释放,或者对于动态开辟的空间未释放,造成程序中出现野指针现象
<0>动态开辟及手动销毁空间

#include
#include
#include

struct Teacher 
{
    char name[62];
    int age;
};
int printarray(struct Teacher *array,int num)
{
    int i=0;
    for(i=0;iprintf("%d ",array[i].age);
    }
    return 0;
}

int sortarray(struct Teacher *tarray,int num )
{
    int i=0,j=0;
    struct Teacher tmp;
    for(i=0;ifor(j=i+1;jif(tarray[i].agereturn 0;
}

struct Teacher * createarray(int count )//动态创建函数
{
    int i=0;
    struct Teacher *p1=(struct Teacher*)malloc(count*sizeof(struct Teacher));
    if( p1 == NULL )
    {
        return NULL;
    }
    for(i=0;imemset(&p1[i],0,sizeof(struct Teacher));

    }
    return p1;
}

void  myfree(struct Teacher *parray)//释放空间函数
{
    if(parray!=NULL)
    {
        free(parray);
        parray=NULL;
    }

}
int  main()
{
    int i=0;
    struct Teacher *parray=createarray(10);
    for(i=0;i<4;i++)
    {
        printf("请输入age:\n");
        scanf("%d",&parray[i].age);
    }
    printf("排序之前:\n");
    printarray(parray,4);

    printf("\n排序之后 \n");
    sortarray(parray,4);
    printarray(parray,4);
    myfree(parray);//内存释放,避免内存泄露
    return 0;
}

结构体做函数参数_第4张图片

<1>结构体嵌套一级指针
在被调函数中分配内存,在主调函数中使用,指针做函数参数,相当于函数的输出端口

#include
#include
#include

struct Teacher 
{
    char name[64];
    char* a_name;//结构体嵌套一级指针
    int age;
};
int printarray(struct Teacher *array,int num)
{
    int i=0;
    for(i=0;iprintf("\n%d   ",array[i].age);
        printf("%s  ",array[i].name);
        printf("%s",array[i].a_name);
    }
    return 0;
}

int sortarray(struct Teacher *tarray,int num )
{
    int i=0,j=0;
    struct Teacher tmp;
    for(i=0;ifor(j=i+1;jif(tarray[i].agereturn 0;
}

struct Teacher * createarray(int count )
{
    int i=0;
    struct Teacher *p1=(struct Teacher*)malloc(count*sizeof(struct Teacher));
    if( p1 == NULL )
    {
        return NULL;
    }
    for(i=0;imemset(&p1[i],0,sizeof(struct Teacher));
        p1[i].a_name=(char*)malloc(128*sizeof(char));//手动为一级指针所指向的内存开辟空间
        memset(p1[i].a_name,0,128*sizeof(char));//初始化
    }
    return p1;
}

void  myfree(struct Teacher *parray,int num)
{
    int i;
    if(parray ==NULL )
    {
        return ;
    }
    for(i=0;iif(parray[i].a_name!=NULL)
//释放指针所指向的内存空间,牢记指针变量和指针所指向的内存空间是两个不同的东西
        {
            free(parray[i].a_name);
        }
//不能这样单独释放name[64];
//因为struct Teacher 是自定义大小的内存空间,不能部分释放
        /*if(parray[i].name !=NULL)
        {
            free(parray[i].name);
        }*/
    }
    if(parray!=NULL)
    {
        free(parray);
        parray=NULL;//垃圾话语
    }
}
int  main()
{
    int i=0;
    struct Teacher *parray=createarray(4);
    for(i=0;i<4;i++)
    {
        printf("请输入age:\n");
        scanf("%d",&parray[i].age);

        printf("请输入name:\n");
        scanf("%s",parray[i].name);

        printf("请输入a_name:\n");
        scanf("%s",parray[i].a_name);
    }
    printf("排序之前:\n");
    printarray(parray,4);

    printf("\n排序之后 \n");
    sortarray(parray,4);
    printarray(parray,4);

    myfree(parray,4);//内存释放,避免内存泄露
    return 0;
}

结构体做函数参数_第5张图片

<2>结构体嵌套二级指针

#include "stdio.h"
#include "stdlib.h"
#include "string.h"


//两个结构体变量之间的copy行为
struct teacher
{
    char name[64];//64
    char *a_name; //4 //结构体里面套一级指针
    int age ; //4
    char **  stuname;//结构体里面套二级指针
};

int printtArray(struct teacher *pArray, int num)
{
    int i = 0;
    int j = 0;
    for (i=0; iprintf("\n %d ", pArray[i].age);
        printf("%s ", pArray[i].name);
        printf("%s ", pArray[i].a_name);

        for (j=0; j<3; j++)
        {
            char **p2 = pArray[i].stuname;
            printf("%s ", p2[j]);
        }
    }
    return 0;
}

int sorttArray(struct teacher *pArray, int num )
{
    int i = 0, j = 0;
    struct teacher tmp;
    for (i=0; i<4; i++)
    {
        for (j=i+1; jif (pArray[i].age < pArray[j].age)
            {
                tmp = pArray[i];
                pArray[i] = pArray[j];
                pArray[j] = tmp;
            }
        }
    }
    return 0;
}

struct teacher*  creatTArray(int count)
{
    int i = 0;int j = 0;
    struct  teacher*p1 = (struct  teacher *)malloc(count*sizeof(struct  teacher ));
    if (p1 == NULL)
    {
        return NULL;
    }
    for (i=0; imemset(&p1[i], 0, sizeof(struct  teacher));
        memset(p1+i, 0, sizeof(struct  teacher));
        p1[i].a_name = (char *)malloc(128*sizeof(char)) ;// char buf[128*4]
        memset(p1[i].a_name , 0, 128*sizeof(char));
        //p1[i].stuname = (char **)malloc(100);

        {
            char **p2 = (char **)malloc(3*sizeof(char *));//p2为局部变量 
            for (j=0; j<3; j++)
            {
                p2[j] =(char *) malloc(128*sizeof(char));//为p2所对应内存开辟动态空间
                memset(p2[j] , 0, 128*sizeof(char));//初始化p2为0
            }
            p1[i].stuname = p2;//将p2挂在学生内存上
        }
    }
    return p1;
}


void free2p(char **p ,int num)//释放p2空间函数
{
    int i = 0; int j = 0;
    for (i=0; iif (p[i] != NULL) 
        {
            free(p[i] );
        }           
    }
    free(p);
}
void freeTArray(struct teacher* tArray, int num)
{
    int i = 0;

    if (tArray == NULL)
    {
        return ;
    }

    for (i=0; ichar *p = tArray[i].a_name; //为什么这里需要释放
        if (p != NULL)
        {
            free(p);
        }

        //释放手工的二维内存
        if (tArray[i].stuname != NULL) 
        {
            free2p(tArray[i].stuname, 3);
        }
    }

    if (tArray != NULL)
    {
        free(tArray);
        tArray = NULL; //垃圾话语
    }
}

void main()
{
    int i = 0; int j = 0;
    struct teacher *pArray  = creatTArray(4);
    if (pArray == NULL)
    {
        return ;
    }

    for (i=0; i<2; i++)
    {
        int tmp = 0;

        char *p = pArray[i].a_name;

        printf("\n请输入age: " );
        scanf("%d", &(pArray[i].age) ) ;

        printf("\n请输入名字: " );
        scanf("%s", pArray[i].name);

        printf("\n请输入别名: " );
        scanf("%s", p);

        for (j=0; j<3; j++)
        {
            char **p2 = pArray[i].stuname;
            printf("\n请输入学生的名字");
            scanf("%s", p2[j]);
        }
    }

    printf("\n排序之前\n");
    printtArray(pArray, 2 );

    printf("\n排序之后\n");
    sorttArray(pArray, 2 );
    printtArray(pArray, 2 );

    freeTArray(pArray, 2);
    system("pause");
}

结构体做函数参数_第6张图片

<3>深拷贝与浅拷贝
从键盘输入赋给t1,再将t1拷贝给t2;
浅拷贝:只是机械的将t1内存空间中的内容拷到t2中,若出现指针,拷贝后的指针则会与原指针指向同一块内存空间,编译器并不会单独为其开辟新的空间,从而会导致对一块空间的多次释放,野指针由此产生;
结构体做函数参数_第7张图片
深拷贝:在函数中,为拷贝函数动态的开辟空间,不再是公用同一块内存,避免将同一块空间重复释放的问题出现;
结构体做函数参数_第8张图片

#include
#include
#include
struct teacher
{
    char name[64];//64
    char *a_name; //4 //结构体里面套一级指针
    int age ; //4
};
int printtArray(struct teacher *pArray, int num)
{
    int i = 0;
    int j = 0;
    for (i=0; iprintf("\n %d ", pArray[i].age);
        printf("%s ", pArray[i].name);
        printf("%s ", pArray[i].a_name);
    }
    return 0;
}

struct teacher*  creatTArray(int count)
{
    int i = 0;int j = 0;
    struct  teacher*p1 = (struct  teacher *)malloc(count*sizeof(struct  teacher ));
    if (p1 == NULL)
    {
        return NULL;
    }
    for (i=0; imemset(&p1[i], 0, sizeof(struct  teacher));
        p1[i].a_name = (char *)malloc(128*sizeof(char)) ;// char buf[128*4]
        memset(p1[i].a_name , 0, 128*sizeof(char));

    }
    return p1;
}


void freeTArray(struct teacher* tArray, int num)
{
    int i = 0;

    if (tArray == NULL)
    {
        return ;
    }
    for (i=0; ichar *p = tArray[i].a_name; //为什么这里需要释放
        if (p != NULL)
        {
            free(p);
        }
    if (tArray != NULL)
    {
        free(tArray);
        tArray = NULL; //垃圾话语
    }
}
}

void mycopy(struct teacher *from,struct teacher *to)
{
    memcpy(to,from,sizeof(struct teacher));
    to->a_name =(char *)malloc(128);
    to->a_name =from->a_name ;
}

//void main()
//{
//  struct teacher* t1=creatTArray(1);
//  struct teacher* t2=creatTArray(1);
//  printf("\n请输入age: " );
//  t1->age=11;
//
//  printf("\n请输入名字: " );
//  strcpy(t1->name ,"t1111");
//
//  printf("\n请输入别名: " );
//  strcpy(t1->a_name ,"t333");
//  //(*t2)=(*t1);//浅拷贝
//  mycopy(&t1,&t2);
//
//
//  system("pause");
//}
void main()
{
    struct teacher t1;
    struct teacher t2;
    printf("\n请输入age: " );
    t1.age=11;
    t1.a_name =(char*)malloc(128);
    strcpy(t1.a_name ,"t333");
    //t2=t1;//浅拷贝
    mycopy(&t1,&t2);//深拷贝要自己开辟空间

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

你可能感兴趣的:(结构体做函数参数)