передача структуры в функцию и её возврат с изменёнными членами
- Войдите на сайт для отправки комментариев
Втр, 21/01/2020 - 11:27
Здравствуйте, уважаемые! Захотелось красивого кода, а главное удобного. Ситуация моя такова: есть 2 переменные типа float rpm; и uint16_t cnt_rpm, которые взаимосвязаны. Есть функция, которая вычисляет их значения. Моя идея объединить rpm и cnt_rpm в структуру, чего ранее не практиковал (прилагаю сначала рабочий код)
struct dataT1{ float rpm; // начальное возможное число оборотов двигателя при clk/1 uint16_t cnt_rpm; // количество ячеек массива при делителе clk/1 } clk_1; struct dataT1 *ptr; void setup() { Serial.begin(9600); ptr = &clk_1; clk_1.rpm = 1.0; clk_1.cnt_rpm = 11; Serial.print("clk_1.rpm = " + String(clk_1.rpm) + "; "); Serial.println("clk_1.cnt_rpm = " + String(clk_1.cnt_rpm) + "; "); Serial.println(" "); get_struct(&clk_1); Serial.print("clk_1.rpm = " + String(clk_1.rpm) + "; "); Serial.println("clk_1.cnt_rpm = " + String(clk_1.cnt_rpm) + "; "); } void loop() { } void get_struct(struct dataT1 *clk1){ clk1->rpm = 0.1; clk1->cnt_rpm = 22; //return clk1; }
Вроде всё работает, структура изменяется после работы функции, но думал получить изменение членов структуры другой функцией, с возвращаемым значением (структурой):
clk_1 = get_struct(&clk_1);
а описание ее такое:
dataT1 get_struct(struct dataT1 *clk1){ clk1->rpm = 0.1; clk1->cnt_rpm = 22; return clk1; }
Так у меня выдаёт ошибку...
Подскажите, как правильно синтаксически написать такой код для функции
clk_1 = get_struct(&clk_1);
Может через указатель
ptr = &clk_1;
как-то это делается...?
Спасибо!
Синтаксически правильно возвращать переменную того же типа, что и в декларации функции. А у Вас выходит, что по декларации подлежит возврату структура, но фактически возвращается указатель.
Декларируйте функцию на возврат указателя.
или
но, это лучше объявить методом самой этой структуры
добавлю, что и "идеологически правильно" всегда работать не с самой структурой, а указателем на нее. Если вы передаете или возвращаете из функции структуру - компилятору приходится создавать ее копию, что при больших обьемах данных может вызвать нехватку памяти. Кроме того, если в вашей структуре будут содержатся ссылки на внешние обьекты - метод с копированием может приводить и к ошибкам.
Вот так:
Всем спасибо! Вот мой рабочий код:
Я правильно всё сделал, так вроде все делают (просмотрел примеры в инете)? Выводит правильные значения членов структуры. Я так понял, чтобы, как писал b707, не создавать копию структуры, с указателем мой код единственный возможный?
Я правильно всё сделал, ..... с указателем мой код единственный возможный?
Нет
Приведите пожалуйста другой пример.
так, у меня снова вопрос, 2 кода, оба работают:
где лучше/хуже/нюансы...? Я так понимаю 2-ой нагляднее показывает, что я передаю функции.
так, у меня снова вопрос, 2 кода, оба работают:
где лучше/хуже/нюансы...? Я так понимаю 2-ой нагляднее показывает, что я передаю функции.
это одно и то же. только во втором случае строка 1 лишняя
Конпилятору вообще пофиг на это жонглирование.
Скорее всего оба варианта сведутся к условному
Я так понял, чтобы, как писал b707, не создавать копию структуры, с указателем мой код единственный возможный?
ошибок в нем нет, но он... несколько странный. Переменная ptr в этом коде вообще лишняя, вы ее ни разу не используете
Хорошо, понял. Теперь вопрос вот в чём. Есть пример
Как мне сделать что-то подобное, если у меня например структура с парами типами float и uint16_t
Как мне описать функцию
чтоб при первом вызове изменялись, например, члены rpm1 и cnt_rpm1, f при втором rpm8 и cnt_rpm8... Как я могу отличить в описании фунукции rpm1 от rpm8? Я про пример с
Как мне описать функцию чтоб при первом вызове изменялись, например, члены rpm1 и cnt_rpm1, f при втором rpm8 и cnt_rpm8... Как я могу отличить в описании фунукции rpm1 от rpm8?
В изложенном примере - никак. Нужно создать две функции, одна будет менять rpm1 и cnt_rpm1, а другая rpm8 и cnt_rpm8
Я так понял, чтобы, как писал b707, не создавать копию структуры, с указателем мой код единственный возможный?
ошибок в нем нет, но он... несколько странный. Переменная ptr в этом коде вообще лишняя, вы ее ни разу не используете
Не понял про переменную ptr, как мне тогда правильно синтаксически написать вызов функции без этой переменной...? Или вы имели ввиду ненужность строки 1?
AlexBajdin59rus, Вы неполностью задали вопрос, а коллеги почему-то повелись и начали отвечать неизвестно на что.
Я вот не знаю как Вам отвечать, т.к. Вы не сказали что должна возвращать Ваша функция - ту же самую структуру или отдельную копию с правильными значениями? Вы разницу понимаете? Если я начну менять поля у возвращённой - должны ли меняться у исходной?
И зачем Вы прицепились к указателям? Это не С, это С++. Используйте ссылки - всё красиво безо всякого синтаксического геморроя.
Не понял про переменную ptr, как мне тогда правильно синтаксически написать вызов функции без этой переменной...?
Вы завели переменную ptr , которая должна указывать на вашу структуру. Но вместо того чтоб использовать ptr при передаче ссылки в функцию и при доступе к полям структуры - вы везде используете не указатель ptr. а непосредственно адрес структуры &clk1. зачем тогда вообще нужен ptr? - если вы выкинете из кода строчки 6 и 11, где упоминается ptr , а строку 20 перепишете без возвращаемого значения:
у вас программа будет работать как ни в чем ни бывало без ptr
поэтому я и говорю, что ptr тут вообще лишний.
Добавка - Евгений выше прав, вы для начала определитесь - что вам нужно - менять исходную структуру или создавать новую с новыми значениями.
AlexBajdin59rus, Вы неполностью задали вопрос, а коллеги почему-то повелись и начали отвечать неизвестно на что.
Я вот не знаю как Вам отвечать, т.к. Вы не сказали что должна возвращать Ваша функция - ту же самую структуру или отдельную копию с правильными значениями? Вы разницу понимаете? Если я начну менять поля у возвращённой - должны ли меняться у исходной?
Разницу в Вашем пояснении и понимаю и немного Вы меня запутали, если честно... Функция, по моим представлениям, должна возвращать ту же самую структуру с изменёнными членами. И я так понимаю это можно сделать только через указатели, чтобы не создавать копию структуры, и как вследствие увеличении ресурсов(если структура большая по размеру), как предупреждал b707.
Если я начну менять поля у возвращённой - должны ли меняться у исходной?
Тут поясню как я Вас понял... Попробую выразить своими словами. При варианте с указателями, возвращённая - это и есть исходная. При варианте с ссылками (если я правильно выражаюсь), у возвращённой (копия структуры) значения копируются в исходную (глобально описанная которая)
И зачем Вы прицепились к указателям? Это не С, это С++. Используйте ссылки - всё красиво безо всякого синтаксического геморроя.
Я пока не проффи в программировании и поэтому пока не знаю разницы в Си и Си++...
Спасибо! Можно тогда от Вас подробное разъяснение, если вас не затруднит.
Нет. с ссылками возвращается таже самая тоже. Новая не создаётся. Но при этом синтаксис гораздо приятнее.
добавлю, что и "идеологически правильно" всегда работать не с самой структурой, а указателем на нее. Если вы передаете или возвращаете из функции структуру - компилятору приходится создавать ее копию, что при больших обьемах данных может вызвать нехватку памяти. Кроме того, если в вашей структуре будут содержатся ссылки на внешние обьекты - метод с копированием может приводить и к ошибкам.
Тогда как понимать это...?
У меня осталось 15 мин, вечером буду пробовать разбираться, но хотелось бы от Вас увидеть рабочий пример, если есть время конечно :). Пример с поста №1, самый простой
Просто хотелось больше наглядности в коде, допустим
то есть сразу видно, что именно структура (левый операнд) изменяет значения своих членов функцией get_struct();
Mожет быть я ввожу в заблуждение названием функцией (нужно написать set_struct(); а не get_struct();
Напишите так: void changeParameters(dataStruct_t& _dataStruct) {...}. Зачем ptr-то лохматить... Сами потом запутаетесь на кой он сдался, а вдобавок кучу ворнингов от компилятора получите.
добавлю, что и "идеологически правильно" всегда работать не с самой структурой, а указателем на нее. Если вы передаете или возвращаете из функции структуру - компилятору приходится создавать ее копию, что при больших обьемах данных может вызвать нехватку памяти. Кроме того, если в вашей структуре будут содержатся ссылки на внешние обьекты - метод с копированием может приводить и к ошибкам.
Тогда как понимать это...?
Я имел в виду, что в процедуру следует передавать или указатель (ptr), или адрес структуры (&clk_1) - а не саму структуру - clk_1, как вы это делали в самом первом своем примере
Добавка - впрочем, читаю других и вижу, что во многом тоже плаваю, так что лучше слушайте Садмана и Евгения
добавлю, что и "идеологически правильно" всегда работать не с самой структурой, а указателем на нее. Если вы передаете или возвращаете из функции структуру - компилятору приходится создавать ее копию, что при больших обьемах данных может вызвать нехватку памяти. Кроме того, если в вашей структуре будут содержатся ссылки на внешние обьекты - метод с копированием может приводить и к ошибкам.
Тогда как понимать это...?
Я имел в виду, что в процедуру следует передавать или указатель (ptr), или адрес структуры (&clk_1) - а не саму структуру - clk_1, как вы это делали в самом первом своем примере
Простите, но я же вроде и передал адрес структуры (&clk_1) в самом первом примере...
разве нет...?
Простите, но я же вроде и передал адрес структуры (&clk_1) в самом первом примере...
разве нет...?
прошу прощения, неточно выразился - передали то вы адрес, а возвращать пытались саму структуру
Ага, понял, тогда мой самый первый пример правильный для работы кода по ссылкам? Вопрос Евгению. Просто убрать 6 и 11 строки