упаковка в структуру, плюсы и минусы
От: pauldr  
Дата: 23.07.06 13:06
Оценка:
Есть функция, типа:
unsgined foo(struct handle_t *handle, int32 *p, unsigned i1, unsigned i2, unsigned i3, int *err, struct a2 *a2);

a2, i[1-3] — имеют на самом деле более осмысленные названия.

проблема в том что те кто хотят использовать эту функцию или проводят code review не могут
запомнить что для чего в этой функции,
и им все время видя
foo(h, p, a + b, (c — d) << 2,...);

приходится заглядывать в ее определение чтобы понять что здесь происходит или чтобы
ее правильно вызвать.

возникла идея (используется C + gcc extensions),
сделать так

unsgined foo(struct handle_t *handle, struct request req)
{
int32 *p = req->p;
unsigned i1 = p->i1;
...
}

а вызывать так
struct request req = {
.p = p,
.i1 = a + b,
};
foo(h, &req);

код становиться понятнее,
но скорость очень критична,
не возникает ли здесь лишней траты процессорного времени?
Re: упаковка в структуру, плюсы и минусы
От: pauldr  
Дата: 23.07.06 13:07
Оценка:
Здравствуйте, pauldr, Вы писали:
P>unsgined foo(struct handle_t *handle, struct request req)
т.е. struct request *req

P>{

P> int32 *p = req->p;
P> unsigned i1 = p->i1;

т.е. req->i1

Re: упаковка в структуру, плюсы и минусы
От: Dair Россия  
Дата: 23.07.06 13:28
Оценка:
Здравствуйте, pauldr, Вы писали:

P>Есть функция, типа:

P>unsgined foo(struct handle_t *handle, int32 *p, unsigned i1, unsigned i2, unsigned i3, int *err, struct a2 *a2);

Мне так кажется — повторение — мать учения.
Все параметры ко всем функциям помнить почти невозможно. А к часто употребимым — вполне возможно.
Поэтому, если в открытом параллельно броузере (или man'е) держать описание этой функции (или хотя бы .h с описанием), то проблема заканчивается за неделю, наверно. В смысле — дальше уже можно и запомнить.

Смысла упаковки в структуру особо не вижу, если честно. Не пятьсот параметров же, право слово.
Re: упаковка в структуру, плюсы и минусы
От: strcpy Россия  
Дата: 23.07.06 13:33
Оценка:
Здравствуйте, pauldr, Вы писали:

P>Есть функция, типа:

P>unsgined foo(struct handle_t *handle, int32 *p, unsigned i1, unsigned i2, unsigned i3, int *err, struct a2 *a2);

Ну если функция и вправду так называется, не мудрено что её прототип вызывает вопросы.
Если прототип правильно описывает параметры, то я полагаю, что тут ужк проблема в IDE, который не доносит эту информацию до пользователя.

Организация структуры имеет смысл только в связи с факторизацией кода, то есть, если создав структуру, вы получите уменьшение объёма существующего кода, то это осмысленно. Иначе подобный рефакторинг кажется мне лишним.
Удвой число ошибок, если не получается добиться цели.
Re: упаковка в структуру, плюсы и минусы
От: Murom Россия  
Дата: 23.07.06 14:03
Оценка:
Здравствуйте, pauldr, Вы писали:

P>Есть функция, типа:

P>unsgined foo(struct handle_t *handle, int32 *p, unsigned i1, unsigned i2, unsigned i3, int *err, struct a2 *a2);

P>a2, i[1-3] — имеют на самом деле более осмысленные названия.


P>проблема в том что те кто хотят использовать эту функцию или проводят code review не могут

P>запомнить что для чего в этой функции,
P>и им все время видя
P>foo(h, p, a + b, (c — d) << 2,...);

P>приходится заглядывать в ее определение чтобы понять что здесь происходит или чтобы

P>ее правильно вызвать.

P>возникла идея (используется C + gcc extensions),

P>сделать так

P>unsgined foo(struct handle_t *handle, struct request req)

P>{
P> int32 *p = req->p;
P> unsigned i1 = p->i1;
P>...
P>}

P>а вызывать так

P>struct request req = {
P>.p = p,
P>.i1 = a + b,
P>};
P>foo(h, &req);

P>код становиться понятнее,

P>но скорость очень критична,
P>не возникает ли здесь лишней траты процессорного времени?

Не понятно почему пераметры функции, относящиеся к одной сущности (i1,i2,i3,a2) идут не подряд? (Вывод об однородности параметров сделан на основе упаковки в одну структуру).
Почему код ошибки вклинился между i3 и a2?

Упаковка в структуру, если и замедлит выполнение, то не сильно.
Вообще вариантов рефакторинга может быть много, смотря что именно надо, читаемости, скорости, ...

P.S. Более осмысленные имена могут помочь в запоминании порядка следования параметров.
- Eugeny
Re: упаковка в структуру, плюсы и минусы
От: vvotan Россия  
Дата: 23.07.06 14:23
Оценка:
Здравствуйте, pauldr, Вы писали:

P>код становиться понятнее,

С точки зрения понятности можно использовать boost::parameter (естественно, если С++, а не голый С)

P>но скорость очень критична,

Но сам не пробовал, как оно работает не знаю
--
Sergey Chadov

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: упаковка в структуру, плюсы и минусы
От: Анатолий Широков СССР  
Дата: 23.07.06 15:06
Оценка:
P>а вызывать так
P>struct request req = {
P>.p = p,
P>.i1 = a + b,
P>};
P>foo(h, &req);

P>код становиться понятнее,

P>но скорость очень критична,
P>не возникает ли здесь лишней траты процессорного времени?

По сути, код равнозначный.
Re[2]: упаковка в структуру, плюсы и минусы
От: Аноним  
Дата: 23.07.06 17:42
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

P>>а вызывать так

P>>struct request req = {
P>>.p = p,
P>>.i1 = a + b,
P>>};
P>>foo(h, &req);

P>>код становиться понятнее,

P>>но скорость очень критична,
P>>не возникает ли здесь лишней траты процессорного времени?

АШ>По сути, код равнозначный.


Не совсем. Структуру как таковую передать проще, чем несколько параметров, в том смысле, что сруктура — это непрерывный участок памяти. Вопрос лишь в том, будет ли тратиться время на копирование параметров в эту структуру. Тогда это будет чуть медленнее, чем прямое их копирование в стэк вызова.
И еще, у автора в прототипе стоит передача по значению, а в вызове — по указателю. О равнозначности может идти речь, только если передача идет по значению.
Re: упаковка в структуру, плюсы и минусы
От: Кодт Россия  
Дата: 24.07.06 11:55
Оценка:
Здравствуйте, pauldr, Вы писали:

<>

Передача россыпи аргументов: возможность использовать конвенцию fastcall (передавать часть из них через регистры).
Передача структуры по значению: дополнительное копирование. Внутри функции доступ к данным прямой (точнее, косвенность относительно указателя стека).
Передача структуры по ссылке/указателю: нет дополнительного копирования, может быть использована fastcall. Зато все обращения — косвенные. И более того, невозможна оптимизация:
struct wrapper { int x; };

void foo(wrapper w)
{
    for(int i=0; i!=w.x; ++i) printf("%d", w.x);
    // эквивалентно коду
    register int wx = w.x;
    for(register int i=0; i!=wx; ++i) printf("%d", wx);
}

void bar(wrapper const* w)
{
    for(int i=0; i!=w->x; ++i) printf("%d", w->x);
    // нет гарантии, что printf не меняет структуру, указатель на которую мы держим... поэтому будем читать каждый раз по-новой
}

то есть вся надежда на кэш процессора.

P.S.
Было бы интересно взглянуть на реальную сигнатуру функции: как она называется и содержательные названия параметров.
Может быть, там не всё так печально.

P.P.S.
Параметры можно группировать. Например,
void strcpy_n_n(char* dst, int dstlen, char const* src, int srclen);
// заменить на
struct strbuf { char* ptr; int len; };
struct const_strbuf { const char* ptr; int len; };
void strcpy_n_n(strbuf, const_strbuf);
...
int main()
{
  char a[100], b[200];
  strcpy_n_n(make_strbuf(a,100), make_const_strbuf(b,200));
}

(Это даже на Си. На С++ вместо make-функций можно и нужно использовать конструкторы).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.