C Struct中的默认值

Art*_*ldt 91 c initialization

我有这样的数据结构:

    struct foo {
        int id;
        int route;
        int backup_route;
        int current_route;
    }

以及一个名为update()的函数,用于请求对其进行更改.

  update(42, dont_care, dont_care, new_route);

这真的很长,如果我在结构中添加一些内容,我必须在每次调用更新(...)时添加'dont_care'.

我正在考虑将结构传递给它,但事先用'dont_care'填充结构比在函数调用中拼写它更加繁琐.我可以使用默认值dont care在某处创建结构,并在我将其声明为局部变量后设置我关心的字段吗?

    struct foo bar = { .id = 42, .current_route = new_route };
    update(&bar);

将我希望表达的信息传递给更新功能的最优雅的方法是什么?

我希望其他一切都默认为-1("不关心"的密码)

hlo*_*dal 153

虽然宏和/或函数(如已经建议的)将起作用(并且可能具有其他积极效果(即调试挂钩)),但它们比需要的更复杂.最简单且可能最优雅的解决方案是仅定义用于变量初始化的常量:

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);
Run Code Online (Sandbox Code Playgroud)

这段代码几乎没有理解间接的精神开销,而且很明显bar你在(安全地)忽略那些未设置的字段时明确设置了哪些字段.

  • 当我改为500行时,"掉线"了该项目.希望我能在这一次投票两次! (23认同)
  • 这种方法的另一个好处是它不依赖于C99功能. (6认同)
  • `PTHREAD_MUTEX_INITIALIZER`也使用它. (4认同)

jpa*_*cek 15

您可以将您的秘密特殊值更改为0,并利用C的默认结构成员语义

struct foo bar = { .id = 42, .current_route = new_route };
update(&bar);
Run Code Online (Sandbox Code Playgroud)

然后将作为初始化程序中未指定的bar成员传递0.

或者您可以创建一个将为您执行默认初始化的宏:

#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);
Run Code Online (Sandbox Code Playgroud)

  • C99:http://open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf:6.7.8.19:初始化应在初始化程序列表顺序中进行,每个初始化程序为特定子对象提供,覆盖之前列出的任何子对象同一子对象的初始化程序; (2认同)
  • 如果这是真的,你能不能定义DEFAULT_FOO,它有所有的初始化器,然后做struct foo bar = {DEFAULT_FOO,.id = 10}; ? (2认同)

Mat*_*t J 7

<stdarg.h>允许您定义可变参数函数(接受无限数量的参数,例如printf()).我将定义一个函数,它接受任意数量的参数对,一个指定要更新的属性,另一个指定值.使用enum或字符串指定属性的名称.


小智 5

也许考虑使用预处理器宏定义:

#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); })
Run Code Online (Sandbox Code Playgroud)

如果你的(struct foo)实例是全局的,那么你当然不需要参数.但我假设你可能有不止一个实例.使用({...})块是适用于GCC的GNU-ism; 这是一种将线条保持在一起的好方法(安全).如果以后需要向宏中添加更多内容,例如范围验证检查,则不必担心会破坏if/else语句等等.

根据您指出的要求,我会这样做.像这样的情况是我开始大量使用python的原因之一; 处理默认参数等变得比以往任何时候都简单得多.(我猜这是一个python插件,对不起;-)