• C语言中结构体參数变量的传递


    【文章摘要

           在C语言中,结构体參数变量常常作为函数的參数来进行传递。但假设參数设置不当。会出现内存问题。

           本文以实际的程序代码为例。具体地介绍怎样正确地使用结构体參数变量。为相关的开发工作提供了參考。

    【关键词

           C语言  结构体  函数  參数  传递

     

    一、前言

           本文中的程序实现对员工信息结构体字段赋值并打印出来的功能。该结构体的定义例如以下:

    // 员工信息结构体

    typedef struct

    {

           INT8       szEmployeeName[100];     // 员工姓名

           UINT16  iEmployeeAge;                    // 员工年龄

           UINT32  iEmployeeNo;                      // 员工工号

    } TEmployeeInfo;

     

            函数GetEmployeeInfo用来对员工信息字段进行赋值。其声明例如以下:

    INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo);

     

           在主函数main中,採用两种參数传递的方法,一种是指针传递。还有一种是非指针传递

     

    二、採用指针传递时的程序代码

           採用指针传递时的程序代码例如以下:

    /**********************************************************************

    * 版权全部 (C)2014, Zhou Zhaoxiong

    *

    * 文件名: TestStruct.c

    * 文件标识:

    * 内容摘要:用于演示结构体变量的使用方法

    * 其他说明:

    * 当前版本号: V1.0

    *     者:周兆熊

    * 完毕日期: 20140617

    *

    * 改动记录1// 改动历史记录, 包含改动日期、版本号号、改动人及改动内容

    * 改动日期: 20140617

    * 号: V1.0

    * 人: Zhou Zhaoxiong

    * 改动内容:创建

    **********************************************************************/

    #include <stdio.h>

    #include <string.h>

     

     

    // 数据类型

    typedef signed   char INT8;

    typedef unsigned char UINT16;

    typedef unsigned int  UINT32;

    typedef signed   int  INT32;

     

     

    // 员工信息结构体

    typedef struct

    {

           INT8    szEmployeeName[100];  // 员工姓名

           UINT16  iEmployeeAge;         // 员工年龄

           UINT32  iEmployeeNo;          // 员工工号

    } TEmployeeInfo;

     

     

    // 函数声明

    INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo); // 获取员工信息函数

    INT32 main(void);

     

     

    /****************************************************************

    * 功能描写叙述主函数                                            

    * 输入參数                                                 

    * 输出參数                                                

    * 返回值: 0-运行成功  -1-运行失败                           

    * 其他说明:  无                                                

    * 改动日期        版本号号        改动人        改动内容

    * ----------------------------------------------------------------------------------------

    * 20140617        V1.0      Zhou Zhaoxiong     创建

    ****************************************************************/

    INT32 main(void)

    {

        INT32          iRetValue      = 0;       // 该变量用于表示调用GetEmployeeInfo函数返回的值

        TEmployeeInfo *ptEmployeeInfo = NULL;    // 该变量用于存放员工信息

       

        // 调用函数对员工信息字段赋值, 并打印出来

        iRetValue = GetEmployeeInfo(ptEmployeeInfo);

        if (iRetValue != 0)

        {

            printf("exec GetEmployeeInfo failed. ");

            return -1;

        }

           

        printf("员工信息为: 姓名: %s 年龄: %d 工号: %d ", ptEmployeeInfo->szEmployeeName, ptEmployeeInfo->iEmployeeAge, ptEmployeeInfo->iEmployeeNo);

     

        return 0;

    }

     

     

    /**********************************************************************

    * 功能描写叙述:对员工信息字段赋值

    * 输入參数: ptEmployeeInfo: 员工信息结构体

    * 输出參数: ptEmployeeInfo: 员工信息结构体

    * 返回值: 0-成功  -1-失败

    * 其他说明:无

    * 改动日期          版本号号           改动人         改动内容

    * --------------------------------------------------------------------------------------

    * 20140617           V1.0         Zhou Zhaoxiong      创建

    ***********************************************************************/

    INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo)

    {

        // 先对输入的指针參数进行异常推断

        if (ptEmployeeInfo == NULL)

        {

            printf("Input parameter is NULL. ");

            return -1;

        }

     

        strncpy((char *)ptEmployeeInfo->szEmployeeName, "Li Yuanfang", strlen("Li Yuanfang"));   // 对姓名字段赋值

        ptEmployeeInfo->iEmployeeAge = 100;       // 对年龄字段赋值

        ptEmployeeInfo->iEmployeeNo  = 123456;    // 对工号字段赋值

     

        return 0;     // 赋值成功, 返回0

    }

     

             程序的运行结果如图1所看到的:

    图1 採用指针传递时的程序代码运行结果

     

            从图1能够看出,函数GetEmployeeInfo的入參为空,不能实现赋值的功能。

     

    三、改进后的採用指针传递时的程序代码

            既然程序打印出指针为空的信息,那么我们先对传入的指针进行赋值操作是不是就能够了呢?

            改进后的採用指针传递时的程序代码例如以下:

    /**********************************************************************

    * 版权全部 (C)2014, Zhou Zhaoxiong

    *

    * 文件名: TestStruct.c

    * 文件标识:

    * 内容摘要:用于演示结构体变量的使用方法

    * 其他说明:

    * 当前版本号: V1.0

    *     者:周兆熊

    * 完毕日期: 20140617

    *

    * 改动记录1// 改动历史记录, 包含改动日期、版本号号、改动人及改动内容

    * 改动日期: 20140617

    * 号: V1.0

    * 人: Zhou Zhaoxiong

    * 改动内容:创建

    **********************************************************************/

    #include <stdio.h>

    #include <string.h>

     

     

    // 数据类型

    typedef signed   char INT8;

    typedef unsigned char UINT16;

    typedef unsigned int  UINT32;

    typedef signed   int  INT32;

     

     

    // 员工信息结构体

    typedef struct

    {

           INT8    szEmployeeName[100];  // 员工姓名

           UINT16  iEmployeeAge;         // 员工年龄

           UINT32  iEmployeeNo;          // 员工工号

    } TEmployeeInfo;

     

     

    // 函数声明

    INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo); // 获取员工信息函数

    INT32 main(void);

     

     

    /****************************************************************

    * 功能描写叙述主函数                                            

    * 输入參数                                                

    * 输出參数                                                

    * 值: 0-运行成功  -1-运行失败                           

    * 其他说明                                                 

    * 改日期        版本号号        改动人        改动内容

    * --------------------------------------------------------------------------------------------

    * 20140617        V1.0      Zhou Zhaoxiong     创建

    ****************************************************************/

    INT32 main(void)

    {

        INT32          iRetValue      = 0;       // 该变量用于表示调用GetEmployeeInfo函数返回的值

        TEmployeeInfo *ptEmployeeInfo = NULL;    // 该变量用于存放员工信息

     

        // 先对员工信息字段赋值, 防止空指针的存在

        strncpy((char *)ptEmployeeInfo->szEmployeeName, "Di Renjie", strlen("Di Renjie"));   // 对姓名字段赋值

        ptEmployeeInfo->iEmployeeAge = 150;       // 对年龄字段赋值

        ptEmployeeInfo->iEmployeeNo  = 654321;    // 对工号字段赋值

       

        // 调用函数对员工信息字段赋值, 并打印出来

        iRetValue = GetEmployeeInfo(ptEmployeeInfo);

        if (iRetValue != 0)

        {

            printf("exec GetEmployeeInfo failed. ");

            return -1;

        }

           

        printf("员工信息为: 姓名: %s 年龄: %d 工号: %d ", ptEmployeeInfo->szEmployeeName, ptEmployeeInfo->iEmployeeAge, ptEmployeeInfo->iEmployeeNo);

     

        return 0;

    }

     

     

    /**********************************************************************

    * 功能描写叙述:对员工信息字段赋值

    * 输入參数: ptEmployeeInfo: 员工信息结构体

    * 输出參数: ptEmployeeInfo: 员工信息结构体

    * 值: 0-成功  -1-失败

    * 其他说明:

    * 改动日期          版本号号           改动人         改动内容

    * -----------------------------------------------------------------------------------

    * 20140617           V1.0         Zhou Zhaoxiong      创建

    ***********************************************************************/

    INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo)

    {

        // 先对输入的指针參数进行异常推断

        if (ptEmployeeInfo == NULL)

        {

            printf("Input parameter is NULL. ");

            return -1;

        }

     

        strncpy((char *)ptEmployeeInfo->szEmployeeName, "Li Yuanfang", strlen("Li Yuanfang"));   // 对姓名字段赋值

        ptEmployeeInfo->iEmployeeAge = 100;       // 对年龄字段赋值

        ptEmployeeInfo->iEmployeeNo  = 123456;    // 对工号字段赋值

     

        return 0;     // 赋值成功, 返回0

    }

     

              程序的运行结果如图2所看到的:

    图2 改进后的採用指针传递时的程序代码运行结果

     

           可见。程序出现了内存问题。原因是在传递之前,ptEmployeeInfo指针已经指向了确定的地址,不能让同一个指针同一时候指向不同的地址。

     

    四、第二次改进后的程序代码

            既然不能用指针作为參数进行传递,那么我们就要考虑另外的方法。

            下面代码採用非指针的传递方式:

    /**********************************************************************

    * 版权全部 (C)2014, Zhou Zhaoxiong

    *

    * 文件名: TestStruct.c

    * 文件标识:

    * 内容摘要:用于演示结构体变量的使用方法

    * 其他说明:

    * 当前版本号: V1.0

    *     者:周兆熊

    * 完毕日期: 20140617

    *

    * 改动记录1// 改动历史记录, 包含改动日期、版本号号、改动人及改动内容

    * 改动日期: 20140617

    * 号: V1.0

    * 人: Zhou Zhaoxiong

    * 改动内容:创建

    **********************************************************************/

    #include <stdio.h>

    #include <string.h>

     

     

    // 数据类型

    typedef signed   char INT8;

    typedef unsigned char UINT16;

    typedef unsigned int  UINT32;

    typedef signed   int  INT32;

     

     

    // 员工信息结构体

    typedef struct

    {

           INT8    szEmployeeName[100];  // 员工姓名

           UINT16  iEmployeeAge;         // 员工年龄

           UINT32  iEmployeeNo;          // 员工工号

    } TEmployeeInfo;

     

     

    // 函数声明

    INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo); // 获取员工信息函数

    INT32 main(void);

     

     

    /****************************************************************

    * 功能描写叙述主函数                                            

    * 输入參数                                                 

    * 输出參数                                                

    * 值: 0-运行成功  -1-运行失败                           

    * 其他说明                                                

    * 改动日期        版本号号        改动人        改动内容

    * --------------------------------------------------------------

    * 20140617        V1.0      Zhou Zhaoxiong     创建

    ****************************************************************/

    INT32 main(void)

    {

        INT32         iRetValue     = 0;      // 该变量用于表示调用GetEmployeeInfo函数返回的值

        TEmployeeInfo tEmployeeInfo = {0};    // 该变量用于存放员工信息

       

        // 调用函数对员工信息字段赋值, 并打印出来

        iRetValue = GetEmployeeInfo(&tEmployeeInfo);

        if (iRetValue != 0)

        {

            printf("exec GetEmployeeInfo failed. ");

            return -1;

        }

           

        printf("员工信息为: 姓名: %s 年龄: %d 工号: %d ", tEmployeeInfo.szEmployeeName, tEmployeeInfo.iEmployeeAge, tEmployeeInfo.iEmployeeNo);

     

        return 0;

    }

     

     

    /**********************************************************************

    * 功能描写叙述:对员工信息字段赋值

    * 输入參数: ptEmployeeInfo: 员工信息结构体

    * 输出參数: ptEmployeeInfo: 员工信息结构体

    * 值: 0-成功  -1-失败

    * 其他说明:

    * 改动日期          版本号号           改动人         改动内容

    * --------------------------------------------------------------

    * 20140617           V1.0         Zhou Zhaoxiong      创建

    ***********************************************************************/

    INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo)

    {

        // 先对输入的指针參数进行异常推断

        if (ptEmployeeInfo == NULL)

        {

            printf("Input parameter is NULL. ");

            return -1;

        }

     

        strncpy((char *)ptEmployeeInfo->szEmployeeName, "Li Yuanfang", strlen("Li Yuanfang"));   // 对姓名字段赋值

        ptEmployeeInfo->iEmployeeAge = 100;       // 对年龄字段赋值

        ptEmployeeInfo->iEmployeeNo  = 123456;    // 对工号字段赋值

     

        return 0;     // 赋值成功, 返回0

    }

     

            程序的运行结果如图3所看到的:

    图3第二次改进后的程序代码运行结果

     

            从图3能够看出。程序运行结果正确,得到了我们想要的结果。

     

    五、总结

            在编写代码的过程中,我们须要注意下面方面:

           (1) 程序头部、函数头部及重要的程序语句处一定要有凝视,这体现了软件开发者的专业素质。

           (2) 函数中出现的变量在定义的同一时候要进行初始化,函数在调用之前一定要先进行声明。

           (3) 对于函数中的指针变量參数,在使用之前一定要先进行异常推断(即推断其是否为NULL)。

           (4) 对于有返回值的函数。要用不同的返回值来差别不同的运行结果。并在重要的地方打印出提示信息。方便对代码的调试。

     

            指针是C语言的精华所在,同一时候也是难点所在。对于一个合格的软件开发project师来说。一定要熟练掌握指针的使用方法。

     

     

     

    (本人微博:http://weibo.com/zhouzxi?topnav=1&wvr=5,微信号:245924426。欢迎关注!

    )

  • 相关阅读:
    twitter分享问题(三)——Required oauth_verifier parameter not provided
    旋转数组的最小数字
    关系型数据库基础之:简单的数据查询
    twitter分享问题(一)——MISSING_ARG_APIKEY
    extern "C"的理解
    从一个链接错误探究GCC的链接库顺序
    GAE 博客——B3log Solo 0.4.0 正式版发布了!
    不使用资源文件动态创建对话框的做法
    GAE 博客——B3log Solo 0.4.0 正式版发布了!
    CodeBlocks启动多个进程实例的做法
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5060828.html
Copyright © 2020-2023  润新知