c语言中结构体中默认值,C Struct中的缺省值
C Struct中的缺省值
我有这样的数据结构:
struct foo {
int id;
int路由;
int backup_route;
int current_route;
}
和一个叫做update()的函数,用来请求它的变化。
更新(42,dont_care,dont_care,new_route);
这真的很长,如果我添加一些东西的结构,我必须添加一个'dont_care'每EVERY更新(…)。
我正在考虑传递一个结构,而不是事先在“dont_care”中填充结构,而不是在函数调用中拼写。 我可以创build结构的默认值不考虑的地方,只是设置我关心的领域之后,我声明它作为一个局部variables?
struct foo bar = {.id = 42,.current_route = new_route};
更新(巴);
什么是最优雅的方式来传递我想expression更新function的信息?
我希望其他所有的东西都默认为-1('不关心'的密码)
虽然macros和/或函数(如已经提到的)将会工作(并且可能具有其他的积极效果(即,debugging钩子)),但是它们比需要的更复杂; 最简单也可能是最优雅的解决scheme是只定义一个用于variables初始化的常量:
const struct foo FOO_DONT_CARE = { // or maybe FOO_DEFAULT or something dont_care, dont_care, dont_care, dont_care }; ... struct foo bar = FOO_DONT_CARE; bar.id = 42; bar.current_route = new_route; update(&bar);
这段代码实际上没有理解间接性的精神上的开销,并且非常清楚你明确设置的是什么字段(安全地)忽略那些你没有设置的字段。
您可以将您的秘密特殊值更改为0,并利用C的默认结构成员语义
struct foo bar = { .id = 42, .current_route = new_route }; update(&bar);
然后会传递0作为初始化器中未指定的bar的成员。
或者你可以创build一个macros来为你做默认的初始化:
#define FOO_INIT(...) { .id = -1, .current_route = -1, .quux = -1, ## __VA_ARGS__ } struct foo bar = FOO_INIT( .id = 42, .current_route = new_route ); update(&bar);
允许您定义可变参数函数(接受无限个参数,如printf() )。 我将定义一个函数,它接受任意数量的参数对,其中一个指定要更新的属性,另一个指定值。 使用enum或string来指定属性的名称。
也许考虑使用预处理器macros定义:
#define UPDATE_ID(instance, id) ({ (instance)->id= (id); }) #define UPDATE_ROUTE(instance, route) ({ (instance)->route = (route); }) #define UPDATE_BACKUP_ROUTE(instance, route) ({ (instance)->backup_route = (route); }) #define UPDATE_CURRENT_ROUTE(instance, route) ({ (instance)->current_route = (route); })
如果(struct foo)的实例是全局的,那么当然你不需要这个参数。 但我假设你可能有不止一个实例。 使用({…})块是适用于GCC的GNU主题; 这是一个很好的(安全)的方式来保持线路作为一个块。 如果以后需要向macros中添加更多内容,比如范围validation检查,则不必担心会破坏if / else语句等等。
这就是我要做的,根据你所要求的要求。 像这样的情况是我开始使用python的原因之一; 处理默认参数等变得比以往任何时候都更简单(我想这是一个python插件,对不起;-)
一个gobject使用的模式是一个可变参数函数,枚举每个属性的值。 界面看起来像这样:
update (ID, 1, BACKUP_ROUTE, 4, -1); /* -1 terminates the parameter list */
因为看起来你只需要这个update()函数的结构,所以根本不要使用这个结构,它只会混淆你构造背后的意图。 你也许应该重新思考为什么你要改变和更新这些字段,并为这个“小”的变化定义单独的函数或macros。
例如
#define set_current_route(id, route) update(id, dont_care, dont_care, route) #define set_route(id, route) update(id, dont_care, route, dont_care) #define set_backup_route(id, route) update(id, route, dont_care, dont_care)
或者更好的写一个函数为每个变化的情况。 正如您已经注意到,您不会同时更改每个属性,因此一次只能更改一个属性。 这不仅可以提高可读性,还可以帮助您处理不同的情况,例如,您不必检查所有的“dont_care”,因为您知道只有当前路线发生了变化。
感觉如何?
struct foo bar; update(init_id(42, init_dont_care(&bar)));
有:
struct foo* init_dont_care(struct foo* bar) { bar->id = dont_care; bar->route = dont_care; bar->backup_route = dont_care; bar->current_route = dont_care; return bar; }
和:
struct foo* init_id(int id, struct foo* bar) { bar->id = id; return bar; }
并相应地:
struct foo* init_route(int route, struct foo* bar); struct foo* init_backup_route(int backup_route, struct foo* bar); struct foo* init_current_route(int current_route, struct foo* bar);
在C ++中,类似的模式有一个我现在不记得的名字。
编辑 :它被称为命名参数成语 。
我生病了结构,所以我可能在这里错过了几个关键字。 但是,为什么不从初始化默认值的全局结构开始,将其复制到本地variables,然后修改它?
初始化程序如下所示:
void init_struct( structType * s ) { memcopy(s,&defaultValues,sizeof(structType)); }
那么当你想使用它:
structType foo; init_struct( &foo ); // get defaults foo.fieldICareAbout = 1; // modify fields update( &foo ); // pass to function
你可以用X-Macro来解决这个问题
你会改变你的结构定义为:
#define LIST_OF_foo_MEMBERS \ X(int,id) \ X(int,route) \ X(int,backup_route) \ X(int,current_route) #define X(type,name) type name; struct foo { LIST_OF_foo_MEMBERS }; #undef X
然后,您将能够轻松定义一个灵活的function,将所有字段设置为dont_care 。
#define X(type,name) in->name = dont_care; void setFooToDontCare(struct foo* in) { LIST_OF_foo_MEMBERS } #undef X
在这里讨论之后,还可以这样定义一个默认值:
#define X(name) dont_care, const struct foo foo_DONT_CARE = { LIST_OF_STRUCT_MEMBERS_foo }; #undef X
其翻译为:
const struct foo foo_DONT_CARE = {dont_care, dont_care, dont_care, dont_care,};
并使用它作为hlovdal答案 , 在这里维护更容易的优势,即改变结构成员的数量将自动更新foo_DONT_CARE 。 请注意, 最后的“虚假”逗号是可以接受的 。
当我必须解决这个问题时,我首先学习了X-Macros的概念。
对于添加到结构中的新字段非常灵活。 如果您有不同的数据types,您可以根据数据types定义不同的dont_care值:从这里 ,您可以从第二个示例中用于打印值的函数获取灵感。
如果您可以使用all int结构,那么您可以省略LIST_OF_foo_MEMBERS的数据types,只需将结构定义的X函数更改为#define X(name) int name;
最优雅的方法是直接更新struct字段,而不必使用update()函数 – 但也许有很好的理由使用它,而不是在问题中遇到。
struct foo* bar = get_foo_ptr(); foo_ref.id = 42; foo_ref.current_route = new_route;
或者像Pukkubuild议的那样,可以为结构的每个字段创build单独的访问函数。
否则,我能想到的最好的解决scheme是将结构字段中的值“0”视为“不更新”标志 – 所以您只需创build一个函数来返回零值结构,然后使用它来更新。
struct foo empty_foo(void) { struct foo bar; bzero(&bar, sizeof (struct bar)); return bar; } struct foo bar = empty_foo(); bar.id=42; bar.current_route = new_route; update(&bar);
但是,如果0是结构中的字段的有效值,则这可能不是非常可行的。
c语言中结构体中默认值,C Struct中的缺省值相关推荐
- C语言程序设计--结构体--计算该日是在本年中是第几天
代码区 C语言程序设计–结构体–计算该日是在本年中是第几天 #include<stdio.h> struct {int year;int month;int day; }date; mai ...
- C语言程序设计——结构体 给定如下定义:struct date_rec { int day ; int month ; int year ; } ; struct date_rec current_
给定如下定义: struct date_rec { int day ; int month ; int year ; } ; struct date_rec cur ...
- C++中结构体与类的区别介绍
在参与以C++为编程基础的项目应用中总会遇到结构体类型与类的数据类型,但是其具体应用区别模糊不清 现将其区别总结如下,欢迎补充共同学习(先介绍C和C++中结构体的不同,再对比C++中结构体与类的区别) ...
- c语言将结构体转换为字符串,[流畅的 C]C语言将结构体转化为字符串
[流畅的 C] C语言将结构体转化为字符串 本文并非标题的具体实现.而是提供一种编程方式,习惯,一种探讨. 本文有一点点门槛,有 socket,开源协议栈学习/开发经验者阅读更佳. Overview ...
- swift string转int_swift中结构体和类的区别(值类型和引用类型的区别)
在swift中结构体和类有着更多的相同之处,在一般的使用中能够做到互相替换.我们可以先看看官方文档的描述: Unlike other programming languages, Swift does ...
- c语言结构体成员变量私有化,C语言中结构体变量私有化详解
C语言中结构体变量私有化详解 背景介绍 操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚 ...
- C语言结构体与C++中结构体和类的区别
在C++中除了类中可以有构造函数和析构函数外,结构体中也可以包含构造函数和析构函数,这是因为结构体和类基本雷同,唯一区别是,类中成员变量默认为私有,而结构体中则为公有.注意,C++中的结构体是可以有析 ...
- C 语言中结构体强制转换--实验
2019独角兽企业重金招聘Python工程师标准>>> 对于C语言中结构体强制转换做了如下实验, 或许可以解惑一些问题 对于结构体, 我理解的属性有: 成员的顺序, 成员的类型,成员 ...
- ios开发中的C语言学习—— 结构体简介
在开发过程中,经常会需要处理一组不同类型的数据,比如学生的个人信息,由姓名.年龄.性别.身高等组成,因为这些数据是由不同数据类型组成的,因此不能用数组表示,对于不同数据类型的一组数据,可以采用结构体来 ...
- c语言实现结构体变量private,C语言中结构体变量私有化详解
背景介绍 操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate ...
最新文章
- MySQL(mysql 5.7)用户密码的管理
- 用计算机测出你真实的年龄,一款神奇的App:能够测出你的真实年龄
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
- [Android工具]安卓音乐下载软件,无损音乐FLAC音乐下载器
- RocketMQ 很慢?引出了一个未解之谜
- 服务器系统与普通系统不同,服务器系统与普通系统区别
- (七)数据结构之“字典”
- Windows: 在系统启动时运行程序、定时计划任务、定时关机
- SAP Spartacus split view里每个元素宽度的计算方式
- SQL Server-聚焦WHERE Column = @Param OR @Param IS NULL有问题?
- Java生鲜电商平台-B2B生鲜的互联网思维
- You can‘t specify target table ‘XXX‘ for update in FROM clause
- 知乎万赞:人并不是活一辈子,而是活几个瞬间
- 如何利用计算机实现非线性转换,基于cass数控绕线机非线性算法的设计与实现-计算机应用技术专业论文.docx...
- kali2020进入单模式_出租车使用“滴滴”平台 司机希望恢复抢单模式 滴滴出行有回应...
- springmvc连接mysql_挺详细的spring+springmvc+mybatis配置整合|含源代码
- mac使用cjk和ctex宏包
- gen-cpp/.deps/ChildService.Plo: No such file or directory
- 麻将胡牌递归算法(lua)
- javaWeb学习笔记(尚硅谷旧版+新版)