The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"копирование структуры в функциях С"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [ Отслеживать ]

"копирование структуры в функциях С"  
Сообщение от ghost_in_machine email on 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 не красиво и сильно страдает читабельность кода. А как сделать идейно правильно?
Спасибо.

Высказать мнение | Ответить | Правка | Cообщить модератору

 Оглавление

Сообщения по теме [Сортировка по времени | RSS]


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

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

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

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

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

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

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

3. "копирование структуры в функциях С"  
Сообщение от const email(??) on 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 толку больше, чем от таких сомнительных фокусов. А если функции большие, то игра не стоит свеч.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

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

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

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру