Перейти к содержанию
    

Возврат структуры из функции

Перечитывая книжку классиков по программированию на языке С, обнаружил, что они возвращают из функции целую структуру. Конкретно, структуру из двух координат точки. Как это (возможно)?

У Шилдта этот вопрос вежливо замалчивается...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как это (возможно)?

Компилатор формирует при вызове функции место в стеке и передает адрес на эту область в функцию. В самой функции структура - локальная переменная (в стеке). Для возвращения структуры компилятор копирует поля локальной структуры по тому адресу, который предоставила функция. По сути у функции есть еще один "невидимый" входной параметр - адрес для возврата.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда это должно называться возврат указателя на структуру.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вы дерзкий! Я бы не решился возвращать из функции указатель на локальную переменную )

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вы дерзкий! Я бы не решился возвращать из функции указатель на локальную переменную )

А никто так и не делает. Возвращают данные, которые компилятор неявно копирует из локальной переменной в lvalue, указатель на который также неявно передается в ф-цию. То есть, возвращаются только данные.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ничего не понимаю. То, что передается в функцию, не имеет отношения к тому, что выдается. Именно так показано в примерах в книге K&R. Давайте ограничимся возвратом.

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

Если можно выдать структуру, то почему нельзя выдать аналогичным образом массив?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда это должно называться возврат указателя на структуру.
Вообще мой пост был обращен к этому посту.

Ну вот так уж повелось. Структуры и присваивать можно друг другу, а вот массивы уже увы. На счет глобальных структур вы погорячились, никто не мешает работать подобным образом и с локальными переменными. Просто примите это как должное и живите дальше спокойно )

Изменено пользователем Bear_ku

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если можно выдать структуру, то почему нельзя выдать аналогичным образом массив?

 

Можно. Для этого он должен быть внутри структуры, которая может быть из одного массива.

 

А аналогичным образом нельзя потому, что массив есть указатель на кусок предвыделенной на этапе компиляции памяти. А структура - есть сам набор данных, а не указатель на него. Поэтому "return <массив>" - ошибочен, так как получается требование возврата указателя, возможно на локальный буфер, время жизни которого кончается с выходом из ф-ции. А "return <структура>" - корректно, так как это требования возврата самих данных, хранящихся в структуре, а не указателя на структуру. Поэтому присваивания и возвраты массивов изначально не предусмотрены, а структур - пожалуйста.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вас же не смущает возврат, например, целого числа. Почему вас смущает возврат структуры?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А аналогичным образом нельзя потому, что массив есть указатель на кусок предвыделенной на этапе компиляции памяти. А структура - есть сам набор данных, а не указатель на него. Поэтому "return <массив>" - ошибочен, так как получается требование возврата указателя, возможно на локальный буфер, время жизни которого кончается с выходом из ф-ции. А "return <структура>" - корректно, так как это требования возврата самих данных, хранящихся в структуре, а не указателя на структуру. Поэтому присваивания и возвраты массивов изначально не предусмотрены, а структур - пожалуйста.

Кто же им (K&R) мешал сделать структуры и массивы одинаковыми в смысле обращения к ним - или адрес, или агрегатный тип данных?

Допустим, получили результат функции - структуру. Единственное, что приходит на ум - сохранить ее в своей (локальной, глобальной) переменной - структуре. И потом использовать ее отдельные члены. К чему вся эта чехарда?

 

Вас же не смущает возврат, например, целого числа. Почему вас смущает возврат структуры?

Число или указатель передается одним регистром.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Единственное, что приходит на ум - сохранить ее в своей (локальной, глобальной) переменной - структуре. И потом использовать ее отдельные члены.

Ну вот именно так они и сделали! Оператор "return" сохраняет ее в этой самой, (локальной, глобальной) переменной. Что не нравится-то?

 

Число или указатель передается одним регистром.

Ни в одном стандарте С нет понятия регистров, и вообще, каких либо требований к реализации на каких либо архитектурах. Так что, это высказывание совершенно некорректно. А вдруг у процессора вообще регистров нет, к примеру, только стек, и все?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Число или указатель передается одним регистром.
А если число "шире", чем регистр. Например, long long int? Или вообще double?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Будем считать что я осознал и раскаялся... (хотя разницу с массивом считаю надуманной)

 

Вот что пишут в Procedure Call Standard for the ARM Architecture.

 

5.4 Result Return

The manner in which a result is returned from a function is determined by the type of that result.

For the base standard:

 A Half-precision Floating Point Type is converted to single precision and returned in r0.

 A Fundamental Data Type that is smaller than 4 bytes is zero- or sign-extended to a word and returned in r0.

 A word-sized Fundamental Data Type (e.g., int, float) is returned in r0.

 A double-word sized Fundamental Data Type (e.g., long long, double and 64-bit containerized vectors) is

returned in r0 and r1.

 A 128-bit containerized vector is returned in r0-r3.

 A Composite Type not larger than 4 bytes is returned in r0. The format is as if the result had been stored in

memory at a word-aligned address and then loaded into r0 with an LDR instruction. Any bits in r0 that lie

outside the bounds of the result have unspecified values.

 A Composite Type larger than 4 bytes, or whose size cannot be determined statically by both caller and

callee, is stored in memory at an address passed as an extra argument when the function was called (§5.5,

rule A.4). The memory to be used for the result may be modified at any point during the function call.

 

Ну вот именно так они и сделали! Оператор "return" сохраняет ее в этой самой, (локальной, глобальной) переменной. Что не нравится-то?

Чтобы использовать структуру, выданную из функции, ее нужно вручную присвоить своей.

Я же не могу выполнить, например, следующее:

myStruct.a = func(...).a;

 

А сначала

myStruct = func(...);

потом работать с членами myStruct.

Или при возврате структура останется в тех же регистрах, и будет считаться уже myStruct?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кто же им (K&R) мешал сделать структуры и массивы одинаковыми в смысле обращения к ним - или адрес, или агрегатный тип данных?

Да они поначалу так и собирались делать, т.е. неуклонно следовать правилу: передача параметров (и возврат) производится по значению.

Но потом подумали и сделали "для удобства" исключение для массивов.

 

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

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

 

Фортран, кстати, придерживается диаметрально противоположной стратегии, там все параметры передаются по ссылке. Так что даже для передачи константы приходится завести для неё где-то в памяти ячейку и передавать в функцию её адрес.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я же не могу выполнить, например, следующее:

myStruct.a = func(...).a;

 

Это Вас кто-то жестко обманул. Можете.

 

myStruct.a = (func(...)).a;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...