C语言中布局体参数变量通报简介
副标题#e#
在C语言中,布局体参数变量常常作为函数的参数来举办通报。但假如参数配置不妥,会呈现内存问题。
本文以实际的措施代码为例,具体地先容如何正确地利用布局体参数变量,为相关的开拓事情提供了参考。
一、媒介
本文中的措施实现对员工信息布局体字段赋值并打印出来的成果。该布局体的界说如下:
// 员工信息布局体 typedef struct { INT8 szEmployeeName[100]; // 员工姓名 UINT16 iEmployeeAge; // 员工年数 UINT32 iEmployeeNo; // 员工工号 } TEmployeeInfo;
函数GetEmployeeInfo用来对员工信息字段举办赋值,其声明如下:
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo);
在主函数main中,回收两种参数通报的要领,一种是指针通报,另一种长短指针通报。
二、回收指针通报时的措施代码
回收指针通报时的措施代码如下:
* 修改记录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 }
#p#副标题#e#
措施的运行功效如图1所示:
图1 回收指针通报时的措施代码运行功效
从图1可以看出,函数GetEmployeeInfo的入参为空,不能实现赋值的成果。
三、改造后的回收指针通报时的措施代码
既然措施打印出指针为空的信息,那么我们先对传入的指针举办赋值操纵是不是就可以了呢?
#p#分页标题#e#
改造后的回收指针通报时的措施代码如下:
修改记录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指针已经指向了确定的地点,不能让同一个指针同时指向差异的地点。
四、第二次改造后的措施代码
既然不能用指针作为参数举办通报,那么我们就要思量别的的要领。
#p#分页标题#e#
以下代码回收非指针的通报方法:
* 修改记录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语言的英华地址,同时也是难点地址。对付一个及格的软件开拓工程师来说,必然要纯熟把握指针的利用要领。
From:csdn博客 周兆熊