Использование struct field в качестве счетчика цикла? - PullRequest
0 голосов
/ 29 ноября 2018

Немного предыстории проблемы

, если у меня есть структура, подобная

typedef struct {
    idx_type type;
    union {
        char *str;
        int num;
    } val
} cust_idx;

, и у меня есть подобные циклы

for (i = 0; i < some_get(x); i++) {
    some_fun(z, NULL, i);
}

, которые я хочу реорганизовать виспользуйте такую ​​структуру, как some_fun(z, idx), где idx является одной из моих cust_idx структур, было бы лучше оставить i в качестве счетчика цикла и обновить idx или изменить заголовок for, чтобы использовать idx.val.num вместоi?

Для этого предположим, что idx_type - это перечисление для строковых и числовых типов, а во всех других полях будут макросы, но я собираюсь использовать только макрос IDX_NUMздесь я не беспокоюсь о том, что делать с idx.type.

Подводя итог моим проблемам:

  1. Будет ли он читабельным?Я не хочу оставлять за собой беспорядок, который кто-то прочтет и просто покачал головой ...
  2. Не рекомендуется ли это?
  3. Какое из них является лучшим решением?

Поле Struct как счетчик цикла

#define IDX_NUM(x) (x.val.num)
...
cust_idx j;
j.type = TYPE_num;
for (IDX_NUM(j) = 0; IDX_NUM(j) < some_get(x); IDX_NUM(j)++) {
    some_fun(z, j);
}

Это то же самое, что и оригинал, но использование поля / макроса struct расширяет и усложняет заголовок цикла for, на мой взгляд, но все еще довольно понятно,

Изменить структуру с помощью оригинального счетчика

cust_idx j;
j.type = TYPE_num;
for (i = 0; i < some_get(x); i++) {
    IDX_NUM(j) = i;
    some_fun(z, j);
} 

Это логически приводит к наименьшим изменениям по сравнению со старым кодом, но в конечном итоге приведет к наибольшему количеству кода из-за добавления строк назначения.

Указатель на поле структуры

cust_idx j;
int *i = &(j.val.num);
j.type = TYPE_num;
for ((*i) = 0; (*i) < some_get(x); (*i)++) {
    some_fun(z, j);
} 

Я не уверен, насколько хорошо это будет в долгосрочной перспективе, или если это не рекомендуется.

1 Ответ

0 голосов
/ 29 ноября 2018

Что касается читабельности, я бы всегда предпочел отдельные счетчики циклов.

РЕДАКТИРОВАТЬ: следующее в курсив не правильно в этом конкретном случае , поскольку C структурируетзначения по умолчанию передаются как копии значений по стеку, поэтому передача от j до some_fun () в цикле - это нормально.Но я оставлю здесь предостережение, поскольку оно применимо ко многим подобным ситуациям, когда структура или массив передаются значением указателя.(он же «передается по ссылке»).

Это особенно верно в коде, который вы опубликовали, когда вы вызываете функцию со структурой в качестве аргумента внутри цикла.Если я не знаю, что делает some_fun (), я могу только надеяться, что член структуры, который я использую в качестве счетчика цикла, не изменяется.И надежда не является стратегией.

Так что, если нет очень веских причин поступать иначе, я всегда ставлю читабельность на первое место.Помните: если вы пишете код, который ограничивает ваши собственные синтаксические и семантические возможности, вам будет очень мало отладки такого кода, так как отладка на порядок сложнее, чем написание (глючного) кода.;)

Дополнение: Вы можете посмотреть разборки всех вариантов.Компилятор может выполнить здесь много оптимизаций, особенно если он может «увидеть» some_fun ().

...