реклама на сайте
подробности

 
 
> Возврат структуры из функции, косяк Кернигана-Ричи
ViKo
сообщение Feb 9 2015, 07:04
Сообщение #1


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Перечитывая книжку классиков по программированию на языке С, обнаружил, что они возвращают из функции целую структуру. Конкретно, структуру из двух координат точки. Как это (возможно)?
У Шилдта этот вопрос вежливо замалчивается...
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Grizzzly
сообщение Feb 9 2015, 07:26
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 565
Регистрация: 22-02-13
Пользователь №: 75 748



Цитата(ViKo @ Feb 9 2015, 10:04) *
Как это (возможно)?

Компилатор формирует при вызове функции место в стеке и передает адрес на эту область в функцию. В самой функции структура - локальная переменная (в стеке). Для возвращения структуры компилятор копирует поля локальной структуры по тому адресу, который предоставила функция. По сути у функции есть еще один "невидимый" входной параметр - адрес для возврата.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 9 2015, 12:09
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Grizzzly @ Feb 9 2015, 13:26) *
Компилатор формирует при вызове функции место в стеке и передает адрес на эту область в функцию. В самой функции структура - локальная переменная (в стеке). Для возвращения структуры компилятор копирует поля локальной структуры по тому адресу, который предоставила функция. По сути у функции есть еще один "невидимый" входной параметр - адрес для возврата.

Не смотрел в листинг, но сомневаюсь что компилятор что-то передаёт неявно в функцию (кроме указателя this член-функциям), так как соглашения вызова расписаны и там нет предусмотрено это. Да и незачем.
Если функция возвращает структуру, то она "сама об этом знает". И она знает, что вызывающая функция позаботилась о месте в стеке, и просто вычисляет адрес, исходя из SP в точке входа в функцию. Думаю так.
Вообще - это дефолтный способ передачи и возврата параметров в функцию - через стек. И только оптимизатор заменяет стек на входе и выходе функции на регистры (если может и это не запрещено опциями).
Так что компилятор в точке вызова функции по дефолту должен сперва сформировать стековый фрейм для возвращаемого значения (вне зависимости от его типа), а потом поместить в него входные аргументы вызова.

И ещё замечание: насколько я знаю, некоторые компиляторы (согласно соглашениям вызова) могут возвращать не в одном регистре, а в паре. Т.е. в IAR for ARM - если возвращаемое значение - long long, то используется
регистровая пара R0:R1, а не стек. То же самое и для структур - если размер структуры влезает в одну регистровую пару, то она будет возвращена через регистры (один R0 или пару R0:R1), а не через стек.

Вроде так.
Go to the top of the page
 
+Quote Post
SM
сообщение Feb 9 2015, 12:41
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(jcxz @ Feb 9 2015, 15:09) *
Не смотрел в листинг, но сомневаюсь что компилятор что-то передаёт неявно в функцию

Вот неверующих-то развелось sm.gif Вообще-то, это в документации на ABI прописано. Вот пример:

Код
typedef struct {
  int a;
  int b;
  int c;
} T;

T my_func (int a)
{
  T v;

  v.a = a;
  v.b = ~a;
  v.c = -a;
  return v;
}

static T s;

void my_func1(int a)
{
  s = my_func(a);
}


а вот фрагмент вызова ф-ции:

Код
; 30   :
; 31   :   s = my_func(a);

    mov    eax, DWORD PTR _a$[ebp]
    push    eax
    lea    ecx, DWORD PTR $T792[ebp]
    push    ecx
    call    _my_func
    add    esp, 8
    mov    edx, DWORD PTR [eax]
    mov    DWORD PTR _s, edx
    mov    ecx, DWORD PTR [eax+4]
    mov    DWORD PTR _s+4, ecx
    mov    edx, DWORD PTR [eax+8]
    mov    DWORD PTR _s+8, edx


push eax - педерача параметра "a"
lea и push ecx - неявная передача указателя на область стека для возврата структуры
затем вызов функции, и копирование результата в статическую переменную.

А вот если бы структура состояла бы из двух int, а не трех - то все бы упростилось. Оба поля вернулись бы в edx:eax без стека и неявных указателей.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- ViKo   Возврат структуры из функции   Feb 9 2015, 07:04
||- - Grizzzly   Цитата(SM @ Feb 9 2015, 15:41) а вот фраг...   Feb 9 2015, 12:45
|- - Grizzzly   Цитата(jcxz @ Feb 9 2015, 15:09) Не смотр...   Feb 9 2015, 12:42
|- - SM   Цитата(Grizzzly @ Feb 9 2015, 15:42) Возм...   Feb 9 2015, 12:43
- - ViKo   Тогда это должно называться возврат указателя на с...   Feb 9 2015, 07:45
|- - Bear_ku   Цитата(ViKo @ Feb 9 2015, 12:45) Тогда эт...   Feb 9 2015, 08:52
- - Bear_ku   А вы дерзкий! Я бы не решился возвращать из фу...   Feb 9 2015, 08:15
|- - SM   Цитата(Bear_ku @ Feb 9 2015, 11:15) А вы ...   Feb 9 2015, 08:29
|- - ar__systems   Цитата(SM @ Feb 9 2015, 03:29) А никто та...   Mar 13 2015, 15:17
|- - XVR   Цитата(ar__systems @ Mar 13 2015, 18:17) ...   Mar 16 2015, 12:21
- - ViKo   Ничего не понимаю. То, что передается в функцию, н...   Feb 9 2015, 08:52
|- - SM   Цитата(ViKo @ Feb 9 2015, 11:52) Если мож...   Feb 9 2015, 09:00
|- - ViKo   Цитата(SM @ Feb 9 2015, 12:00) А аналогич...   Feb 9 2015, 09:09
|- - SM   Цитата(ViKo @ Feb 9 2015, 12:08) Единстве...   Feb 9 2015, 09:11
|- - andrew_b   Цитата(ViKo @ Feb 9 2015, 12:09) Число ил...   Feb 9 2015, 09:13
|- - SSerge   Цитата(ViKo @ Feb 9 2015, 16:09) Кто же и...   Feb 9 2015, 09:33
- - andrew_b   Вас же не смущает возврат, например, целого числа....   Feb 9 2015, 09:05
- - ViKo   Будем считать что я осознал и раскаялся... (хотя р...   Feb 9 2015, 09:27
- - SM   Цитата(ViKo @ Feb 9 2015, 12:27) Я же не ...   Feb 9 2015, 09:34


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 06:37
Рейтинг@Mail.ru


Страница сгенерированна за 0.01468 секунд с 7
ELECTRONIX ©2004-2016