Не передается структура в качестве параметра в функцию?

Тема в разделе "Arduino & Shields", создана пользователем DrProg, 8 июл 2015.

  1. DrProg

    DrProg Вечный нерд

    Я где то ошибся или структура не передается в принципе? Код в упрощенном виде:

    Код (Text):

    struct bstr {
      int a;
      int b;
    };

    bstr aaa;


    void setup() {
      // put your setup code here, to run once:
    aaa.a=20;
    aaa.b=100;
    }

    void loop() {
      // put your main code here, to run repeatedly:
    sert (aaa);
    }

    void sert (bstr ewr) {
    }

     
     
    Последнее редактирование: 8 июл 2015
  2. geher

    geher Гуру

    Можно попробовать добавить struct в объявлении параметра функции.
    Помнится, периодически в C/C++ наступал на эти грабли, что периодически требовалось при объявлении переменной или параметров указывать не просто имя структурного типа, а полностью, предваряя ключевым словом struct.
    В результате я объявления параметров и переменных структурного типа всегда так пишу.

    Т.е. конкретно для данного кода:

    struct bstr aaa;

    void sert (struct bstr ewr) {
     
    DrProg нравится это.
  3. codingmonkey

    codingmonkey Нерд

    я сегодня тоже обломался и указателем и ссылкой пытался передать структуру в процедуру.
    можно так еще попробовать с ID'шками )
    в глобальных объявлениях
    struct {
    int a;
    int b;
    } blob[10];

    void doSomeWorkWithBlob( int i )
    {
    blob...
    }

    >Т.е. конкретно для данного кода:
    т.е. это просто С? а не С++ классов тут нету ?
     
  4. DrProg

    DrProg Вечный нерд

    Попробовал. В этом случае ошибок не пишет, но изменение переменной в структуре внутри функции не передается наружу. Как бы сделать так, чтоб передавалось?

    Вычитал, что можно через указатели, вроде бы выход, но как то громоздко. Есть варианты более стандартные как с обычными переменными?
    Код (Text):

    struct bstr {
      int a;
      int b;
    };

    bstr aaa;

    int sss;

    void setup() {
      // put your setup code here, to run once:
      aaa.a = 20;
      aaa.b = 100;
      sss = 200;
    Serial.begin(9600);
    }

    void loop() {
      // put your main code here, to run repeatedly:
      sert(&aaa);
      Serial.println(aaa.a);
      Serial.println(aaa.b);
      while(true);

    }

    void sert (struct bstr *ewr) {
      ewr->a = 3000;
      ewr->b = 5000;
    }
     
     
  5. Megakoteyka

    Megakoteyka Оракул Модератор

    Структуры передаются, но обычно это делается через указатель.
    Код (Text):
    struct myStruct {
      int a;
    };
    ...
    void func(struct myStruct* pMyStruct)
    {
      int x = pMyStruct->a;
    }
    Если структура передается по значению, то она полностью копируется. Если в функции изменить поля структуры, то исходная структура останется такой же, какой была.
    В случае же передачи структуры через указатель в функцию копируется только указатель на исходную структуру и любые изменения полей структуры будут происходить именно в той структуре, которую передали в функцию.
     
    DrProg нравится это.
  6. geher

    geher Гуру

    По ссылке:
    По факту передается указатель, а в коде функции пользуется как просто переменная
    void sert (struct bstr &ewr) {
     
  7. Megakoteyka

    Megakoteyka Оракул Модератор

    Ничего громоздкого. Добавляется одна звездочка в прототипе функции, а вместо точек пишутся стрелки ->.
    Можно еще передавать по ссылке. При этом реально структура передается через указатель, но обращаться с ней можно как с обычной структурой (это относится к переменным всех типов). Но через указатель все же более наглядно.
     
    DrProg нравится это.
  8. DrProg

    DrProg Вечный нерд

    Наверное, скорее непривычно, чем громоздко. Вы правы, в принципе ничего страшного и, пожалуй, это единственный способ не разбивать структуру на стандартные переменные для ее модификации внутри функции.
     
  9. Megakoteyka

    Megakoteyka Оракул Модератор

    Программирование на С очень похоже на астрологию - по расположению звездочек в коде программист пытается понять, что будет делать программа.
     
  10. DrProg

    DrProg Вечный нерд

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

    Да, кстати, а если в функцию так же передать, например массив по значению и там его изменить, он тоже не выйдет наружу измененным? То есть без указателей (прямого оперирования с памятью) функция может вернуть только одну переменную стандартного типа?
     
  11. Megakoteyka

    Megakoteyka Оракул Модератор

    Очень рекомендую внимательно изучить раздел про указатели в любом учебнике по С/С++.
    Указатели - мощный инструмент, при помощи которого можно писать красивый, лаконичный, эффективный код. Но и напортачить при использовании указателей очень легко.
     
  12. geher

    geher Гуру

    С массивом интереснее. Имя массива - указатель на него же.
    Потому если у нас
    Код (Text):
    int x[10];
    f(int* y){
      y[0]=1;
    }
    ...
    f(x);
    nj y[0]=1; будет по факту менять непосредственно нулевой элемент массива x
     
  13. DrProg

    DrProg Вечный нерд

    По моему это обрывок кода без вызова функции и с неполным ее определением, нет?
     
  14. Unixon

    Unixon Оракул Модератор

    Обращение к пространству имен или к члену класса.

    Код (Text):

    namespace solarsystem
    {

    namespace earth
    {
     const int planet_id = 3;
     struct population
    {
     long long humans;
     long long robots;
     long long aliens;
    }
    }

    namespace mars
    {
     const int planet_id = 4;
     struct population
    {
     long long humans;
     long long robots;
     long long aliens;
    }
    }

    }

    int get_most_populated_planet()
    {
     long long earth_population = solarsystem::earth::population.humans + solarsystem::earth::population.robots + solarsystem::earth::population.aliens;
     long long mars_population = solarsystem::mars::population.humans + solarsystem::mars::population.robots + solarsystem::mars::population.aliens;
     if (earth_population>mars_population) return solarsystem::earth::planet_id; else return solarsystem::mars::planet_id;
    }
     
    Обратите внимание, идентификаторы в разных пространствах имен могут пересекаться.
     
    Последнее редактирование: 9 июл 2015
  15. DrProg

    DrProg Вечный нерд

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

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

    Megakoteyka Оракул Модератор

    Вы без них не обходитесь на самом деле. Вот взять хотя бы класс Serial, без которого практически ни один скетч не обходится. Большинство библиотек сделаны в виде классов.
     
  17. DrProg

    DrProg Вечный нерд

    Использовать классы без проблем, а вот надо ли их писать? Не ради того, чтобы написать, а когда действительно иначе не обойтись, как вот например сегодня с передачей указателя структуры в функцию. Изучить возможность все равно как минимум интересно, но хотелось бы практической пользы.
     
  18. Unixon

    Unixon Оракул Модератор

    Когда у вас в коде начинают формироваться [возможно, достаточно большие, но не обязательно] подсистемы, ответственные за какую-то функциональность, имеет смысл их разграничить, разнеся в разные пространства имен дабы избежать возможных конфликтов идентификаторов. А то и вовсе бывает удобно в разных подсистемах иметь одинаковые методы типа initialize(), configure(), shutdown() и т.п., а общий префикс (имя подсистемы) вынести в имя пространства. Это примерно как если у вас бы было несколько классов, но всего могло бы существовать всего по одному объекту каждого класса. Тогда объектный подход не особо нужен и можно реализовать все в процедурном стиле используя вместо классов пространства имен.

    Тут все очень просто. У вас есть структуры и есть функции, которые эти структуры обрабатывают. Есть два варианта, как это можно записать: а) передавать каждый раз указатель на структуру явно в качестве параметра всех функций, имеющих отношение к этой структуре; б) объявить класс и все поля (константы, переменные) и методы (функции) объявить внутри него, в это случае параметр [указатель на экземпляр структуры] становится неявным. Ну, это в первом приближении, без углубления в детали. Кстати, структуры в C++ могут содержать не только поля, но и функции! По сути они ничем не отличаются от классов, у которых все поля и методы объявлены как public.

    а) void foo(my_class_t *object, ...);
    b) object.foo(...);
     
    DrProg нравится это.
  19. Unixon

    Unixon Оракул Модератор

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

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

    Дальше начинаются виртуальные методы с динамическим связыванием, позволяющие буквально на ходу подставлять разные реализации совместимые по интерфейсу с базовым классом.
     
  20. ИгорьК

    ИгорьК Гуру

    :) сахар...