URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 7528
[ Назад ]

Исходное сообщение
"копирование структуры в функциях С"

Отправлено ghost_in_machine , 06-Авг-08 13:42 
Здравствуйте. Вопрос по С. Допустим, есть структура на 32битной машине
typedef struct { short a, b; } t_bi_short;
или ее идейные аналоги на 64битной
typedef struct { int a, b; } t_bi_int;
typedef struct { short a, b, c, d; } t_thetra_short;
С такой структурой бывает удобно работать т.к. она имеет размерность регистра и ее можно копировать, передавая в функцию копию данных, а не указатель на них. Но формально язык не поддерживает таких приемов, и приходиться писать что-то типа:
void function(int arg);
и вызывать как
{
t_bi_short bi_short;
…..
function(*(int*)&bi_short);
}

Все работает, нo не красиво и сильно страдает читабельность кода. А как сделать идейно правильно?
Спасибо.


Содержание

Сообщения в этом обсуждении
"копирование структуры в функциях С"
Отправлено Michelnok , 06-Авг-08 16:57 
>
>А как сделать идейно правильно?

Идейно правильно - не рассчитывать на размерность вообще.

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


"копирование структуры в функциях С"
Отправлено ghost_in_machine , 06-Авг-08 17:33 
>>
>>А как сделать идейно правильно?
>
>Идейно правильно - не рассчитывать на размерность вообще.
>
>Непонятно также, что вы особо выигрываете, передавая в функцию данные, а не
>указатель на них. Если эти данные ложатся в стек, то процессору
>все равно за ними лезть в память, по адресу в стеке.
>Если передаются через регистры - то все равно они туда попадают
>из памяти же, при вызове.

Спасибо за ответ.
Выигрышей несколько:
1) если данные надо портить, то их придется в функции явно копировать из указателя,
2) часто (особенно на 64 битах) можно выполнить 2 операции одной командой над структурой. Ну, к примеру, сдвигать два индекса массива одновременно простым суммированием, или инициализировать/сравнивать одним равенством/условием. Вероятно компилятор это оптимизирует как-то и без меня, но мне так спокойнее за критические куски кода :),
3) функция может возвращать 2 аргумента вместо одного напрямую, а не через аргумент-указатель, да и вообще количество аргументов уменьшаеться.
Короче, выгоду можно подытожить как: мелочь, а приятно. :)


"копирование структуры в функциях С"
Отправлено const , 06-Авг-08 20:27 
struct val { short a, b, c, d; };
struct val f1(short x) { return (struct val){x, x, x, x}; }
short f2(struct val v) { return v.a ^ v.b ^ v.c ^ v.d; }

...и аналогично для двух других структур: с двумя интами и с двумя шортами.
Под amd64 всё в ажуре: f1 возвращает результат в RAX, f2 достаёт v из RDI.
Под i386 хуже: обе функции берут параметры со стека и от этого никуда не деться без ассемблера (да и с ним трудновато). К тому же, f1 кладёт результат обратно в стек, и это опять же протокол вызова функций (другими словами, c'est la vie).
А на какой-нибудь ещё суровой машине вполне может оказаться sizeof(struct val) > 4 * sizeof(short) и весь разговор не будет иметь никакого смысла.

Если функции, которые вы пытаетесь оптимизировать, маленькие, то напишите их реализацию в хедере: от inline толку больше, чем от таких сомнительных фокусов. А если функции большие, то игра не стоит свеч.


"копирование структуры в функциях С"
Отправлено ghost_in_machine , 07-Авг-08 11:14 
>[оверквотинг удален]
>v из RDI.
>Под i386 хуже: обе функции берут параметры со стека и от этого
>никуда не деться без ассемблера (да и с ним трудновато). К
>тому же, f1 кладёт результат обратно в стек, и это опять
>же протокол вызова функций (другими словами, c'est la vie).
>А на какой-нибудь ещё суровой машине вполне может оказаться sizeof(struct val) > 4 * sizeof(short) и весь разговор не будет иметь никакого смысла.
>
>Если функции, которые вы пытаетесь оптимизировать, маленькие, то напишите их реализацию в
>хедере: от inline толку больше, чем от таких сомнительных фокусов. А
>если функции большие, то игра не стоит свеч.

Спасибо за ответ.
Amd64 является целевой платформой для моего проекта.
Касательно больших функций, то данные часто надо доставлять к зубодробилке через ряд подготовительных процедур. Соответственно, единообразие их представления облегчает проверку логики алгоритма. Этот факт только увеличивает ценность вашего ответа, СПАСИБО.