Значения по умолчанию в Структуре C

Я был неправ. MS word не поддерживает формат .docx . Вместо этого используйте формат .doc , который будет поддерживаться в обоих приложениях !!!

91
задан hlovdal 22 June 2009 в 18:20
поделиться

9 ответов

While macros and/or functions (as already suggested) will work (and might have other positive effects (i.e. debug hooks)), they are more complex than needed. The simplest and possibly most elegant solution is to just define a constant that you use for variable initialisation:

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);

This code has virtually no mental overhead of understanding the indirection, and it is very clear which fields in bar you set explicitly while (safely) ignoring those you do not set.

153
ответ дан DevSolar 24 November 2019 в 06:45
поделиться

Вы можете изменить свое специальное секретное значение на 0, и использовать семантику членов структуры C по умолчанию

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

тогда передаст 0 как члены bar, не указанные в инициализатор.

Или вы можете создать макрос, который будет выполнять инициализацию по умолчанию за вас:

#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);
15
ответ дан jpalecek 24 November 2019 в 06:45
поделиться

позволяет вам определять переменные функции (которые принимают неопределенное количество аргументов, например printf () ). Я бы определил функцию, которая принимает произвольное количество пар аргументов, одна из которых определяет свойство, которое будет обновляться, а другая - значение. Используйте перечисление или строку, чтобы указать имя свойства.

7
ответ дан Matt J 24 November 2019 в 06:45
поделиться

Возможно, стоит рассмотреть возможность использования макроопределения препроцессора:

#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) является глобальным, то вам, конечно, не нужен этот параметр. Но я предполагаю, что у вас, вероятно, более одного экземпляра. С использованием ({ ... }) блок - это GNU-изм, применимый к GCC; Это хороший (безопасный) способ объединить строки в блок. Если вам позже потребуется добавить больше в макросы, например, проверку валидации диапазона, вам не придется беспокоиться о нарушении таких вещей, как операторы if / else и т. Д.

Это то, что я хотел бы сделать, исходя из требований Вы указали. Подобные ситуации являются одной из причин того, что я начал часто использовать python; обработка параметров по умолчанию и тому подобное становится намного проще, чем когда-либо с C. (я думаю, это плагин Python, извините; -)

на основе указанных вами требований. Подобные ситуации являются одной из причин того, что я начал часто использовать python; обработка параметров по умолчанию и тому подобное становится намного проще, чем когда-либо с C. (я думаю, это плагин Python, извините; -)

на основе указанных вами требований. Подобные ситуации являются одной из причин того, что я начал часто использовать python; обработка параметров по умолчанию и тому подобное становится намного проще, чем когда-либо с C. (я думаю, это плагин Python, извините; -)

5
ответ дан digijock 24 November 2019 в 06:45
поделиться

Один из объектов, используемых в шаблонах, - это функция с переменными числами и перечисляемые значения для каждого свойства. Интерфейс выглядит примерно так:

update (ID, 1,
        BACKUP_ROUTE, 4,
        -1); /* -1 terminates the parameter list */

Написание функции varargs легко - см. http://www.eskimo.com/~scs/cclass/int/sx11b.html . Просто сопоставьте пары ключ -> значение и установите соответствующие атрибуты структуры.

4
ответ дан John Millikin 24 November 2019 в 06:45
поделиться

Как насчет чего-то вроде:

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 ++ аналогичный шаблон имеет имя, которое я сейчас не помню.

РЕДАКТИРОВАТЬ : Он называется Идиома именованного параметра .

4
ответ дан Paddu 24 November 2019 в 06:45
поделиться

Самый элегантный способ - обновить поля структуры напрямую, без использования функции update () функция - но, может быть, есть веские причины для ее использования, которые не встречаются в этом вопросе.

struct foo* bar = get_foo_ptr();
foo_ref.id = 42;
foo_ref.current_route = new_route;

Или вы можете, как предложил Пукку, создать отдельные функции доступа для каждого поля структуры.

В противном случае лучшее решение, которое я могу придумать, - это обрабатывать значение «0» в поле структуры как флаг «не обновлять» - так что вы просто создаете функцию для возврата обнуленной структуры, а затем используете ее для обновления.

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 является допустимым значением для полей в структуре.

1
ответ дан Noldorin 24 November 2019 в 06:45
поделиться

Since it looks like that you only need this structure for the update() function, don't use a structure for this at all, it will only obfuscate your intention behind that construct. You should maybe rethink why you are changing and updating those fields and define separate functions or macros for this "little" changes.

e.g.


#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)

Or even better write a function for every change case. As you already noticed you don't change every property at the same time, so make it possible to change only one property at a time. This doesn't only improve the readability, but also helps you handling the different cases, e.g. you don't have to check for all the "dont_care" because you know that only the current route is changed.

4
ответ дан quinmars 24 November 2019 в 06:45
поделиться

I'm rusty with structs, so I'm probably missing a few keywords here. But why not start with a global structure with the defaults initialized, copy it to your local variable, then modify it?

An initializer like:

void init_struct( structType * s )
{
   memcopy(s,&defaultValues,sizeof(structType));
}

Then when you want to use it:

structType foo;
init_struct( &foo ); // get defaults
foo.fieldICareAbout = 1; // modify fields
update( &foo ); // pass to function
2
ответ дан 24 November 2019 в 06:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: