Вложенные структуры и объявление функции - ошибка :(
- Войдите на сайт для отправки комментариев
Привет всем!
Никогда не программировал на С++, сейчас пытаюсь разобраться. Наткнулся на ошибку, которую не могу объяснить. Спецы, взгляните, пожалуйста, где я накосячил?
struct input_device { uint8_t node; uint8_t addr; // ОШИБКА ТУТ uint8_t comptype; uint8_t data; uint8_t priority; }; struct struct_rules { char *ruleName; uint8_t node; uint8_t out_addr; uint8_t action; input_device input1; input_device input2; uint8_t priority; uint8_t duration; uint32_t dimmer; }; struct_rules rules[5]; void setup() { ... } void loop() { ... } void addrule(struct_rules rule) { rules[1] = rule; }
Что получается:
Структура со вложенной подструктурой активно используется, ошибок компилятора не вызывает (еще не отлаживалось, прога недописана). При попытке объявления функции addrule() компилятор выдает ошибку на строке объявления вложенной структуры:
SH_Node.ino:21:14: error: variable or field 'addrule' declared void
SH_Node.ino:21:14: error: 'struct_rules' was not declared in this scope
Была глупая мысль насчет совпадения первых 4 символов функции и переменной, но не подтвердилось, переименование функции ничего не дает, ошибка та же.
И второй глупый вопрос.
Если я создаю переменную типа struct_rules, заполняю её, в том числе заполняю данные подчиненной структуры:
struct_rules rules[5]; rule[1].node = 1; ... rule[1].input1.node = 0; rule[1].input1.addr = 5; ...
могу я потом в другую переменную передать данные только вложенной подструктуры?
input_device device1; device1 = rules[1].input1;
Простите за глупые вопросты, прошу сильно не пинать начинающего ;)
Не нашел, как тут отредактировать свое сообщение. Во втором вопросе, естественно, опечатка - имя массива в объявлении и заполнении д.б. одинаковым. И по всему второму вопросу - в реальной программе компилятор на похожую конструкцию не ругается, вот только что окажется в переменной device1 - я не могу пока узнать, еще не дошел до стадии отладки.
По второму вопросу, в device1 будет копия из rules[1].input1
Спасибо, я так на это надеялся!
Другой вопрос, зачем держать копию, если можно использовать указатель.
В скопированной в переменную структуре нужно изменять некоторые реквизиты, оставив исходный эталон нетронутым. Так что тут оправдано.
А вообще я указатели понимаю пока только в общих чертах, практически еще с ними работать не умею.
А по первому вопросу - пока приходится использовать линейное программирование, дабы обойти ошибку :(
По первому вопросу много писать с телефона неудобно. Подобные темы есть на форуме.
Что бы не писать слово struct, можно использовать typedef в объявлении структуры.
по Вашему первому вопросу: так, как у Вас объявлено, выражение struct_rules не является полноценным типом данных и его не везде можно использовать как тип. Полное название типа - "struct struct_rules". Вот такая программа откомпилируется нормально.
Опа, как много я еще не знаю... Спасибо!
Только, знаете, Вы уверены, что хотите сделать именно это? При такой передаче параметра у Вас в функции addrule будет создаваться собственная копия аргумента. Это можно делать, если Вам это действительно нужно.
как будет выглядеть передача аргумента в виде ссылки? Пока не вкурил синтаксис указателей :(
void
addrule(
struct
struct_rules & rule)
Это не указатель, а именно ссылка, т.е. при вызове функции просто пишете имя переменной (без каких-либо значков), а внутри функции пользуетесь тоже как обычно "rule. ..." (безо всяких "->" и прочих страстей).
Да, и ещё, в дополнение.
Если Вы реально НЕ хотите менять структуру аргумент внутри функции, то имеет смысл сказать об этом компилятору. Примерно так:
void
addrule(const
struct
struct_rules & rule)
Это касается не только структур и не только аргументов функций - общее правило "хорошего тона": Если изменять переменную не планируется, её нужно объявить константой.
Это даёт сразу две выгоды:
Выгода 1: если из-за ошибки, опечатки и т.п. Вы всё-таки соберётесь её поменять, компилятор этого не пропустит - обругается и убережёт Вас от поиска трудно-диагностируемой ошибки в рабочем коде.
Выгода 2: сообщив компилятору, что данная переменная не изменяется (т.е. является константой) Вы развязываете ему руки для оптимизации кода. Воспользуется ли он этим - зависит от компилятора и конкретной ситуации, но общее правило - не собираетесь менять - объявляйте константой.
Хорошим тоном считается передавать указателем то, что меняется и константной ссылкой то что не меняется.
Спасибо, получилось! Интересно, кто быстрее поумнеет, Умный дом с моей помощью или я с его? ;)
Не за что.
А умнеть - это взаимный процесс :) Я вон на старости лет решил электронику поизучать (по профессии я программист), так начал заниматься с внуком - он и не догадывается, что я практически не его учу, а с ним вместё всё изучаю.