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中的缺省值相关推荐

  1. C语言程序设计--结构体--计算该日是在本年中是第几天

    代码区 C语言程序设计–结构体–计算该日是在本年中是第几天 #include<stdio.h> struct {int year;int month;int day; }date; mai ...

  2. 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 ...

  3. C++中结构体与类的区别介绍

    在参与以C++为编程基础的项目应用中总会遇到结构体类型与类的数据类型,但是其具体应用区别模糊不清 现将其区别总结如下,欢迎补充共同学习(先介绍C和C++中结构体的不同,再对比C++中结构体与类的区别) ...

  4. c语言将结构体转换为字符串,[流畅的 C]C语言将结构体转化为字符串

    [流畅的 C] C语言将结构体转化为字符串 本文并非标题的具体实现.而是提供一种编程方式,习惯,一种探讨. 本文有一点点门槛,有 socket,开源协议栈学习/开发经验者阅读更佳. Overview ...

  5. swift string转int_swift中结构体和类的区别(值类型和引用类型的区别)

    在swift中结构体和类有着更多的相同之处,在一般的使用中能够做到互相替换.我们可以先看看官方文档的描述: Unlike other programming languages, Swift does ...

  6. c语言结构体成员变量私有化,C语言中结构体变量私有化详解

    C语言中结构体变量私有化详解 背景介绍 操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚 ...

  7. C语言结构体与C++中结构体和类的区别

    在C++中除了类中可以有构造函数和析构函数外,结构体中也可以包含构造函数和析构函数,这是因为结构体和类基本雷同,唯一区别是,类中成员变量默认为私有,而结构体中则为公有.注意,C++中的结构体是可以有析 ...

  8. C 语言中结构体强制转换--实验

    2019独角兽企业重金招聘Python工程师标准>>> 对于C语言中结构体强制转换做了如下实验, 或许可以解惑一些问题 对于结构体, 我理解的属性有: 成员的顺序, 成员的类型,成员 ...

  9. ios开发中的C语言学习—— 结构体简介

    在开发过程中,经常会需要处理一组不同类型的数据,比如学生的个人信息,由姓名.年龄.性别.身高等组成,因为这些数据是由不同数据类型组成的,因此不能用数组表示,对于不同数据类型的一组数据,可以采用结构体来 ...

  10. c语言实现结构体变量private,C语言中结构体变量私有化详解

    背景介绍 操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate ...

最新文章

  1. MySQL(mysql 5.7)用户密码的管理
  2. 用计算机测出你真实的年龄,一款神奇的App:能够测出你的真实年龄
  3. 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
  4. [Android工具]安卓音乐下载软件,无损音乐FLAC音乐下载器
  5. RocketMQ 很慢?引出了一个未解之谜
  6. 服务器系统与普通系统不同,服务器系统与普通系统区别
  7. (七)数据结构之“字典”
  8. Windows: 在系统启动时运行程序、定时计划任务、定时关机
  9. SAP Spartacus split view里每个元素宽度的计算方式
  10. SQL Server-聚焦WHERE Column = @Param OR @Param IS NULL有问题?
  11. Java生鲜电商平台-B2B生鲜的互联网思维
  12. You can‘t specify target table ‘XXX‘ for update in FROM clause
  13. 知乎万赞:人并不是活一辈子,而是活几个瞬间
  14. 如何利用计算机实现非线性转换,基于cass数控绕线机非线性算法的设计与实现-计算机应用技术专业论文.docx...
  15. kali2020进入单模式_出租车使用“滴滴”平台 司机希望恢复抢单模式 滴滴出行有回应...
  16. springmvc连接mysql_挺详细的spring+springmvc+mybatis配置整合|含源代码
  17. mac使用cjk和ctex宏包
  18. gen-cpp/.deps/ChildService.Plo: No such file or directory
  19. 麻将胡牌递归算法(lua)
  20. javaWeb学习笔记(尚硅谷旧版+新版)

热门文章

  1. 2018年中考计算机考试成绩,2018年北京中考考试科目、时间及成绩公布通知
  2. STM32实现DAC音频播放
  3. webdriver中的截图截图方法
  4. android游戏地图编辑器
  5. JAVA如何在LINUX里编程,如何使用加多宝(jdb)在linux下调试Java程序
  6. QT 连接 MySQL 失败:手动编译 MySQL 驱动插件
  7. deactivate不能关闭venv
  8. source deactivate失败,无法退出虚拟环境
  9. vue spa项目转服务器渲染
  10. 工厂模式,java描述