您的位置:首页 > 编程语言 > C语言/C++

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

2015-12-20 14:18 751 查看
【文章摘要

在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.\n");

return -1;

}

printf("员工信息为: \n姓名: %s\n年龄: %d\n工号: %d\n", 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.\n");

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.\n");

return -1;

}

printf("员工信息为: \n姓名: %s\n年龄: %d\n工号: %d\n", 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.\n");

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.\n");

return -1;

}

printf("员工信息为: \n姓名: %s\n年龄: %d\n工号: %d\n", 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.\n");

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。欢迎关注!

)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: