|
Век живи, век учись..., функции в CodeVision не позволяют возвращать структуры |
|
|
|
Nov 17 2007, 15:00
|

Знающий
   
Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065

|
ну, или скорее это удар в поддых... Ситуация такая. Пишу крупный прокт на CodeWizardAVR V1.25.3 Standard для mega2561. Почти ООП. Почти самопальная ОСь. Сообщения, очереди, синхронизация... Проект разрастается быстро. Сегодня пришел к пониманию того, что сообщения нужно сделать не ввиде простох чисел Код typedef BYTE MSG; , а как в виде структур Код typedef struct { BYTE code; WORD param; } MSG; Предвижу Ваши соображения по поводу неизвестных BYTE и WORD. Где-то в хэдерных файлах у меня есть определение Код typedef unsigned char BYTE; typedef unsigned int WORD; так что все здесь срастается и работает. Переделываю исходники на новый лад и ... получаю удар граблями со стороны CodeVision. Угадайте с трех раз, откуда? Подсказка Цитата Error: ... function must return a pointer to structure раньше было красиво msg = GetMessage(); Сейчас это уже не канает. Даже передать указатель на структуру, как это просит уважаемый CV, нельзя. Ну, не в том смысле что компилятор не пропустит, а в том, что на _какую_именно_структуру? -- Т.е. на ту, которая определяется в функции, -- нельзя. Ибо структура прекратит свое существоание в момент выхода из функции. Указатель невалиден. Значит остается, единственное решение -- наоборот, передавать указатель в функцию. Как-то это все не по-людски...  Я уже было усомнился в своих знаниях языка (1) по передаче структур из функций, а потом в самих компиляторах для микроконтроллеров. Но нет! Ни старый добрый Borland Turbo-C 2.0, ни IAR таких ограничений не налагают. Знаит, это есть причуда CV. Читаем в хэлпах КоудВижина Цитата The old Kernighan & Ritchie style of writing function definitions is not supported. и еще тут Цитата Because some AVR devices have a small amount of SRAM, in order to keep the size of the Data Stack small, it is recommended not to pass structures as function parameters and use pointers for this purpose. Правда, про возврат структур тут прямо ничего не сказано. Но видимо, подрадумевается, что программер понимает, что если передавать структуру в функцию -- это вилы, то уж возврат из функции явно крах всей системы! Народ, не наступайте на мои грабли  Больна-а...
--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
|
|
|
|
|
 |
Ответов
|
Nov 19 2007, 06:38
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(vmp @ Nov 19 2007, 12:32)  Возврат структуры - довольно неудачное решение. Где должна размещаться эта структура? Если с простыми типами все понятно (результат передается в регистрах), то структуру (в общем случае произвольного размера) нужно размещать в памяти. Вопрос в какой? Статическая не подойдет (имеем проблемы с рекурсией и прерываниями), остается динамическая, т.е. стек или куча. Т.е. компилятор на входе в функцию должен создать данную структуру, на выходе из функции заполнить ее (скорее всего скопировав содержимое из локальной структуры). Вызывающая функция должна скопировать результат куда-то ещё и не забыть уничтожить временное хранилище. И оно надо в микроконтроллерной программе? Двойной расход памяти и двойное копирование? Так что либо вообще не использовать структуры для возврата, либо просто передавать указатель в явном виде (всё равно будет оптимальнее). Почему ж так все драматично? Компилятор вполне сам может передать неявный указатель и внутри функции сразу работать с той памятью, где расположена структура (например, в стеке вызывающей функции). Никакого дополнительного копирования и проблем с аллокацией дополнительной памяти тут нет. Приличные компиляторы так и делают. Получается очень эффективно. Пользователю на это заморачиваться не нужно.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Nov 19 2007, 08:03
|

Местный
  
Группа: Свой
Сообщений: 426
Регистрация: 20-01-05
Из: Зеленоград
Пользователь №: 2 070

|
Цитата(dxp @ Nov 19 2007, 09:38)  Никакого дополнительного копирования и проблем с аллокацией дополнительной памяти тут нет. Разве? Итак, чтобы использовать структуру в качестве результата функции, нам в общем случае нужны 3 структуры: 1. Локальная в вызываемой функции. Она заполняется этой функцией и затем её имя используется в операторе return; 2. Неявная переменная на стеке, в которой и будет возвращен результат. 3. Локальная или глобальная переменная в вызывающей функции, которой будет присвоен результат вызова. Разместить все 3 переменные по одному адресу можно только при очень удачном стечении обстоятельств. При запуске простейшего тестового примера на IAR EWARM 4.41A этого не получилось - компилятор совместил только переменные 1 и 2, достигнув всего лишь двойного, а не тройного расхода памяти. Оптимизация -s9.
|
|
|
|
|
Nov 19 2007, 08:50
|

Знающий
   
Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065

|
Цитата(vmp @ Nov 19 2007, 13:03)  Итак, чтобы использовать структуру в качестве результата функции, нам в общем случае нужны 3 структуры: 1. Локальная в вызываемой функции. Она заполняется этой функцией и затем её имя используется в операторе return; 2. Неявная переменная на стеке, в которой и будет возвращен результат. 3. Локальная или глобальная переменная в вызывающей функции, которой будет присвоен результат вызова.
Разместить все 3 переменные по одному адресу можно только при очень удачном стечении обстоятельств. При запуске простейшего тестового примера на IAR EWARM 4.41A этого не получилось - компилятор совместил только переменные 1 и 2, достигнув всего лишь двойного, а не тройного расхода памяти. Оптимизация -s9. Я прошу участников дискуссии не забывать о прозрачности исходных текств в погоне на экономией одного-двух-трех байт. Кроме того, структура имеет размер немного больший, чем размер скалярной переменной, но и не такой уж большой, что бы уже задумываться о передаче указателей. Т.е. это "пограничный" случай для выбора того или иного решения. Неоднозначности здесь много. Я посмотрел ИАРовский листинг. Там структура тоже возвращается неявно. Все правильно, так и должно быть. Опрератор return копирует данные локальной стуктуры по адресу, который пришел в функцию неявно. Т.е. код Код MSG msg;
msg = GetMessage(); в ассемблерном исполнении выглядит как Код MSG msg;
GetMessage(&msg); Т.е. компилятор выполнил "черную" работу, а мы имеем читабельность и легкое понимание исходников. К тому же работа с локальной переменной и возврат ее из GetMessage также выглядят по-человечески: Код MSG local_msg;
local_msg.code = ... local_msg.param = ...
return local_msg; } Заумные тексты программ это не есть высокий уровень профессионализма. Конечно, все это можно реализовать с помощью указателей на структуры, но при этом немного потеряется читабельность. Чуть-чуть тут, чуть-чуть там, вроде немного. Но когда проектов много, и к ним приходится возвращаться через несколько месяцев, честно говоря -- это уже начинает напрягать. Или я не прав?
--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
|
|
|
|
|
Nov 19 2007, 09:17
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(zhevak @ Nov 19 2007, 14:50)  Я прошу участников дискуссии не забывать о прозрачности исходных текств в погоне на экономией одного-двух-трех байт. А где тут прозрачность страдает? Или что вы подразумеваете под прозрачностью? Цитата(zhevak @ Nov 19 2007, 14:50)  Кроме того, структура имеет размер немного больший, чем размер скалярной переменной, но и не такой уж большой, что бы уже задумываться о передаче указателей. Т.е. это "пограничный" случай для выбора того или иного решения. Неоднозначности здесь много. Вариант с указателем проигрывает (на AVR) только для размера структуры, меньшего размера указателя. В остальных случаях он или не хуже, или лучше. Цитата(zhevak @ Nov 19 2007, 14:50)  Заумные тексты программ это не есть высокий уровень профессионализма.
Конечно, все это можно реализовать с помощью указателей на структуры, но при этом немного потеряется читабельность. Чуть-чуть тут, чуть-чуть там, вроде немного. Но когда проектов много, и к ним приходится возвращаться через несколько месяцев, честно говоря -- это уже начинает напрягать.
Или я не прав? Описанный выше вариант, когда компилятор сам организовывает передачу указателя вполне прозрачен. Для пользователя тут все однозначно - он получает из функции структуру по значению, как и требуется по Стандарту. А как это уже сделал компилятор, это дело третье.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Nov 19 2007, 09:39
|

Знающий
   
Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065

|
Цитата(dxp @ Nov 19 2007, 14:17)  А где тут прозрачность страдает? Или что вы подразумеваете под прозрачностью? Прозрачность начинает уменьшаться с появлением звездочек и амперсендов. Например, в Васике нет этого, поэтому тексты программ на нем более прозрачны, чем на Си. Только не надо передергивать, а то уйдем в бессмысленное словоблудие. (Я, к стати, не адепт Васика.) Понятно, что без указателей будет язык -- неязык. Но там где можно обойтись без указателей, зачем их пихать почем зря? Вообще-то речь идет о том, что моя структура могла бы легко быть возвращена по значению даже в регистрах, но компилятор не предоставил такой возможности вообще! Цитата Вариант с указателем проигрывает (на AVR) только для размера структуры, меньшего размера указателя. В остальных случаях он или не хуже, или лучше. Причем здесь AVR? Это у любой платформы. Цитата Описанный выше вариант, когда компилятор сам организовывает передачу указателя вполне прозрачен. Для пользователя тут все однозначно - он получает из функции структуру по значению, как и требуется по Стандарту. А как это уже сделал компилятор, это дело третье. Ага. По-моему, мы говорим об одном и том же, а такое чувство, что стоим по разные стороны.
--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
|
|
|
|
Сообщений в этой теме
zhevak Век живи, век учись... Nov 17 2007, 15:00 Yason Цитата(zhevak @ Nov 17 2007, 16:00) Значи... Nov 17 2007, 15:16 Сергей Борщ Цитата(zhevak @ Nov 17 2007, 17:00) ну, и... Nov 17 2007, 15:27 zhevak Цитата(Yason @ Nov 17 2007, 20:16) Прошу ... Nov 17 2007, 16:54  VDG ЦитатаРазница между МС и моим ГетМессэйджем в том,... Nov 17 2007, 22:46 VDG Я что-то не въезжаю.
ЦитатаИбо структура прекратит... Nov 17 2007, 16:08 WHALE Цитата(VDG @ Nov 17 2007, 19:08) Я что-то... Nov 17 2007, 16:29 zhevak Цитата(VDG @ Nov 17 2007, 21:08) Я что-то... Nov 17 2007, 18:03 WHALE ну и при чем здесь CV?Если вам надо ООП,пространст... Nov 17 2007, 17:08 zhevak Цитата(WHALE @ Nov 17 2007, 22:08) ну и п... Nov 17 2007, 17:24 Сергей Борщ Цитата(WHALE @ Nov 17 2007, 19:08) Паша Х... Nov 17 2007, 17:32 ReAl Цитата(WHALE @ Nov 17 2007, 19:08) почему... Nov 17 2007, 21:35 SlavaG Можно попробовать сделать так:
Кодtypedef union {... Nov 17 2007, 18:30 zhevak Цитата(SlavaG @ Nov 17 2007, 23:30) Можно... Nov 17 2007, 19:21   Непомнящий Евгений Цитата(vmp @ Nov 19 2007, 11:03) Разве?
... Nov 19 2007, 08:43      dxp Цитата(zhevak @ Nov 19 2007, 15:39) Прозр... Nov 19 2007, 10:06      defunct Цитата(zhevak @ Nov 19 2007, 12:39) Прозр... Nov 19 2007, 10:49 IgorKossak Цитата(vmp @ Nov 19 2007, 08:32) Возврат ... Nov 19 2007, 07:43 zhevak я там где-то ранее обещал опубликовать результаты ... Nov 21 2007, 20:18 VDG 12-ти %-ная разница в объёме сгенерировнного кода.... Nov 21 2007, 23:02
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|