Как передать структуру в функцию.
- Войдите на сайт для отправки комментариев
Чт, 24/01/2013 - 14:17
Здравствуйте. Возможно, вопрос вызван моими "плавающими" познаниями в Си. Однако, беглый гуглёж мне не помог и я прошу вашей помощи.
Есть такой код:
struct Joint { byte i; byte j; byte foo; };
Далее я в loop() делаю так:
for (int i=0; i<module_count; i++) { Joint &joint = joints[i]; ........ if (bar()==true) { .... }
В функции bar я хочу сравнить joint.i с joint.j , вернуть ложь или истину, и некоторым образом изменить joint.foo.
Если бы речь шла только о сравнении, я бы передал i и j параметрами. Но как мне передать foo так, что бы иметь возможность изменить его внутри функции?
Можете передать ссылку на .foo (оператором &) или ссылку на всю стуктуру. При передаче переметра по ссылке параметр меняется из функции.
и лучше, наверно, будет
Не совсем понятно, что такое joints, массив указателей или массив структур.
Если массив указателей, то
Если это массив структур, то
Тогда вызов bar должен быть примерно такой, как
Вы самое главное в исходнике не показали, потому приходится придумывать.
Я так понял, что у него это массив структур. Потому что массив указателей - это весьма непросто (нужно самому заботиться о размещении самих структур), и если бы он это умел, этого вопроса бы не было.
Значит выберет второй вариант ;) А вообще ссылочный тип тоже не каждый знает, возможно и ошибка, потому я просто перестраховался.
Да вобщем-то, в случае массивов и параметров - оно само догадывается "где тут указатели использовать" и можно пользоватся как обычной переменными. Только у функции указать ключевое слово struct
Вывод:
Данный код работает и компилится, но бывает что компилятору ардуины сносит мозги и он не хочет воспринимать структуру как параметр функции. Матюкается странными ошибками и не дает скомпилировать. Вообщем "известная ошибка".
Лечение - простое. Выносим объявление типа структуры Joint_t в отдельный .h и делаем ему #include
В этом случае компилятор начинает работать со структурами в качесве параметров без вытребенек. Да и в любом случае - это хороший тон, выносить всякие подобные объявления в отдельный файл. Так что вроде как и "не критичная проблема".
Нет, здесь не то, что нужно вопрошающему.
В функции bar я хочу сравнить joint.i с joint.j , вернуть ложь или истину, и некоторым образом изменить joint.foo.
Если бы речь шла только о сравнении, я бы передал i и j параметрами. Но как мне передать foo так, что бы иметь возможность изменить его внутри функции?
То есть передача "по значению" ему не подходит, нужно передавать "по ссылке". Тут нужно через указатель.
Не совсем понятно, что такое joints, массив указателей или массив структур.
Массив структур.
Покажу реальный кусок скетча:
Компилятор ругается:
То есть передача "по значению" ему не подходит, нужно передавать "по ссылке". Тут нужно через указатель.
ну "просто добавь амперсанд" :)
Вывод:
Всё нормально, ничего особенного. Нужно написать
Номер строки - 20, как у Вас. Кроме этого тип структуры Joint а не Joints.
У меня это скомпилировалось.
Рекомендую форматировать текст, иначе очень сложно разбираться. (Ctrl-T помогает).
Да, передавать структуру с помощью ссылки - не рекомендую (и не только я, в книгах пишут).
По ссылкам передаются только константные структуры, которые не меняются, в этом случае пишется:
Если нужно что то менять внутри структуры, передается по ссылке:
Спорить и переубеждать не собираюсь, писать и отлаживать программы вам.
Спорить и переубеждать не собираюсь, писать и отлаживать программы вам.
А зря. Раз уж взялись "учить стилю", то стоит и объяснить почему (если сами знаете) через указатель более "хороший стиль" (несмотря на большую громоздкость). Иначе это "магия авторитета", а не понимание. И начнут лепится указатели везде, где нужно и не нужно. Или наоборот "да вроде же и так работает" и забъют, на ваш, вообщем-то полезный совет. "Я сказал" - не самый лучий метод обучения програмированию.
А суть тут вот в чем, когда вы используете указатели, то в вызывающем коде вы ВЫНУЖЕНЫ писать амперсанд
И тот кто будет читать код позже, сразу по тому что функция вызывается с амперсандом видит что "функция может изменить содержимое структуры". Это сразу "намек" что параметр изменяемый даже не глядя на реализацию/объявление самой функции. Тот случай когда "лишние буквы" - являеются полезными/информативными при дальнейшем сопровождении кода.
В случае же использования ампераснда в объявлении самой функции, вызов выглядит как
И то что join после этого может изменится - может стать неприятным сюрпризом при отладке (пока не полезешь смотреть реазацию функции detect_approved и не хлопнешь себя по лбу). Из вызывающего кода его "изменчивость" - не видна.
Но знать про такой способ - тоже нужно. Во первых что-бы понимать чужой код, во вторых бывает что "уже написана куча кода", когда структура была не изменяемой, а вот тут добавили одно поле которое будем менять. Встает альтернатива "через указатели что-бы по красивому" (и кучу замен делать, а не всегда это "код который дозволено менять" или просто добавить амперсанд в объявление самой функции. Сделать изменение в одном месте нечего больше не переписывая.
Обучать? У меня такой цели нет. Подтолкнуть к самостоятельному изучению или понять, почему так советуют - это да. Вы обучаете - на мой взгляд этого более чем достаточно. Забьют на совет? Не вопрос, один забьёт, другой подумает, тема то останется и её прочитают не 2-3, а много больше народу. Более того, один хочет учиться, а другой - нет и это уже никакой учебой не заставишь сделать. Стараюсь отвечать на вопросы может не совсем коротко, но и не очень многословно, чтобы не наскучило читать (без намеков и подттекста).
Ардуино достаточно малообъемный контроллер, потому программы, как правило, не очень большие (разумеется бывают и монстры), отсюда, мой опыт программирования бОльших систем (несколько миллионов строк - не только моих, понятно) не всегда корректен к Ардуино программированию, это да, вполне возможно. Надеюсь понятно, что я не хвастаюсь, а просто привожу пример для сравнения, не более того. К тому же программирование в одиночку и в команде - совершенно разные стили и требования, одному проще. Вот и всё, что я хотел сказать.
Ух, клёво!
Я поясню, что происходит:
Весь мой опыт программирования начинается и заканчивается на скриптах на bash'е и питоне. Так вот в питоне, я бы передал в функцию обьект ( detect_approved(joint)), а внутри функции делал бы с ним всё, что захочу. В Си с этим сложнее (или проще? в общем, по-другому), а читать с нуля чем указатель отличается от ссылки и как с ними работать мне лень (зато честно, да). А на таком вот конкретном примере некое понимание появилось. Всем спасибо.
Прошу помощи, есть код в нём структура
Так вот в функции list_object
Строчка
Выводит размер массива корректно.
а вот строчка
выводит ошибку
screen.ino: In function 'void list_object(add)':
screen.ino:14:25: error: no match for 'operator[]' (operand types are 'add' and 'int')
Ничего не выводит, хотя по замыслу должна вывести:
Где ошибка? как правильно передавать массив объектов структуры в функцию?
dancnik , вы спутали структуры с классами. http://www.c-cpp.ru/books/struktury
Для того что бы объявить переменную предствителя структуры надо писать 3 (три ) слова , а не 2 (два) слова как в классе.
struct
database functionName();
http://learnc.info/c/structures.html
Да все проще, он думает, что передает в функцию массив, а передает копию первого элемента массива.
Между структурой и классом очень маленькая разница в области видимости по умолчанию.
вы спутали структуры с классами.
Сиё невозможно, т.к. элементы определённые ключевыми словами class, struct и union - все являются классами.
del
И здесь весна, обострение. Не форум, а сплошное словоблудие стало.
Всем удачи.
Аллаху Акбар!