|
static variable |
|
|
|
Apr 4 2016, 06:22
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Baser @ Apr 3 2016, 17:38)  При "правильном" программировании Но такой подход убивает чистоту функции, а в некоторых языках программирования чистота функции большой плюс. Функцию с внутренней переменной step не особенно запихнешь в библиотеку для повторного использования. С многопоточностью будут проблемы у такой функции. Совпадение имен глобальной и локальной переменной тоже лучше не практиковать - попутать что где легче простого.
|
|
|
|
|
Apr 5 2016, 04:55
|

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

|
QUOTE (adnega @ Apr 4 2016, 12:22)  Но такой подход убивает чистоту функции, а в некоторых языках программирования чистота функции большой плюс. Функцию с внутренней переменной step не особенно запихнешь в библиотеку для повторного использования. С многопоточностью будут проблемы у такой функции. Ну, с глобальной переменной будет ровно то же самое. Что касается полезности, то завит от. У локальных статических функций есть свои плюсы. Например, функции-генераторы. Или тот же синглтон Мейерса. Реализация получается простая и эффективная. Конечно, в любом случае программист должен чётко представлять, что он делает и какие последствия могут возникнуть из-за неправильного использования. QUOTE (adnega @ Apr 4 2016, 12:22)  Совпадение имен глобальной и локальной переменной тоже лучше не практиковать - попутать что где легче простого. Это да. К слову, глобальных переменных нужно стараться избегать, во всяком случае, минимизировать их количество.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Apr 5 2016, 08:04
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(dxp @ Apr 5 2016, 07:55)  Ну, с глобальной переменной будет ровно то же самое. А если все необходимые переменные передавать в функцию (в виде списка или сложного объекта)? Разумеется, что совсем без побочных действий не обойтись, но если данные можно отделить от кода, то я такой возможностью пользуюсь. Тут пример для управления шаговым двигателем приводили. Предложенная реализация возможна для одного двигателя, а если их много больше? Я бы сделал массив объектов, которые бы хранили все необходимое - и текущий шаг, и скорость, и ускорение, и целевое значение, обратную связь по энкодеру или потенциометру, адреса пинов, если это необходимо. А функцию, решающую что делать с полем step, сделал бы универсальной. Разумеется static переменных в ней не было бы. Оформил бы это в виде библиотеки и таскал из проекта в проект, где есть хоть один шаговый двигатель.
|
|
|
|
|
Apr 5 2016, 10:13
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(adnega @ Apr 4 2016, 09:22)  Но такой подход убивает чистоту функции, а в некоторых языках программирования чистота функции большой плюс. С многопоточностью будут проблемы у такой функции. С этим никто не спорит, но нужно решать в каждом конкретном случае, как будет удобней. Цитата Функцию с внутренней переменной step не особенно запихнешь в библиотеку для повторного использования. А вот тут никто вам не запрещает это делать. Более того, в стандартных библиотеках Си полно функций с таким финтом, в описаниях отдельно пишут, что они "опасные", не реентерабельные, дописывают новые варианты безопасных, но нестандартных функций. Но стандартные функции то уже никуда не денешь  Вот пример, функция парсинга текстовых строк strtokЦитата Совпадение имен глобальной и локальной переменной тоже лучше не практиковать - попутать что где легче простого. Одинаковые глобальные и локальные переменные тоже не советую применять. А вот одинаковые локальные и статические внутри функций - очень даже можно применять. Цитата(adnega @ Apr 5 2016, 11:04)  А если все необходимые переменные передавать в функцию (в виде списка или сложного объекта)? Такой подход тоже имеет место быть, когда есть несколько одинаковых кусков кода обработки. Цитата(Сергей Борщ @ Apr 5 2016, 11:52)  Все это хорошо, но локальные данные могут быть и константными (скажем, таблица для перевода номера микрошага в коэф... Для таблиц и констант можно применять указатели, которые тоже передаются в функцию. Можно передавать также и переменные свойства таблиц (длину, структуру). Много чего можно придумать, главное чтобы понятность кода не страдала. А то сам иногда так накручу код для компактности, потом смотрю на тот ужОс, который получился и понимаю, что написание "тупо в лоб методом copy-paste" было бы лучше
|
|
|
|
|
Apr 5 2016, 10:48
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Baser @ Apr 5 2016, 12:13)  Для таблиц и констант можно применять указатели, которые тоже передаются в функцию. Порой проще и естественней засунуть таблицу в функцию. Например, таблицу перекодировки тетрады в ASCII для вывода чисел в шестнадцатиричном формате. Такая таблица больше нигде не понадобится, какой смысл ее выностить из функции? Цитата(Baser @ Apr 5 2016, 12:13)  А то сам иногда так накручу код для компактности, потом смотрю на тот ужОс, который получился и понимаю, что написание "тупо в лоб методом copy-paste" было бы лучше  Серега, ты созрел для перехода на C++
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 5 2016, 12:08
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(Сергей Борщ @ Apr 5 2016, 13:48)  Серега, ты созрел для перехода на C++  Увы, все никак... Даже осилил почти весь учебник Шилдса, но до конца прочуствовал только одну фразу во введении, где говорится, что смысл применять плюсы есть только начиная с определенного уровня сложности проектов. У меня проекты сравнительно простые, поэтому я никак не пойму для чего мне все эти фантики (обертки) которые скрывают реальную сущность объектов. С переходом с асма на си было все понятно, выгоды очевидны, а тут...
|
|
|
|
|
Apr 7 2016, 07:03
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(Baser @ Apr 5 2016, 15:08)  где говорится, что смысл применять плюсы есть только начиная с определенного уровня сложности проектов. Да что этот Шилдс понимает... :-) Я осваивал плюсы на scmRTOS ("кишки" довольно сложные, но снаружи всё просто и понятно) и на Qt (супер-понятный внешний интерфейс, в "кишки" даже не лазил). Рекомендую! После этого свои классы без особых проблем придумываются. При этом проекты не сказать, чтоб прямо сложные. Пара сотен килобайт исходников - это немного совсем...
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Apr 7 2016, 07:35
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Сергей Борщ @ Apr 5 2016, 13:48)  ...созрел для перехода на C++  Мой первый сиобразный язык был С++, а не С. В незапамятные времена, когда только появился первый (первый, потому, что 1.0 версии не было  ) борлондячий Борланд С++ 2.0 я получил персональный компьютер и решил сваять для работы некую приблуду для которой требовалась, то, что я назвал, "оконной библиотекой" - то есть всякие окошки, текстовые естественно, но все же типа "Windows". В КБ у меня уже был уже бывалый сишный программисто, который утверждал, что писать нужно на Си с большими вкраплениями ASM, иначе будет безумно медленно. В обшем-то он был прав, поскольку тогдашний массовый персональный компьютер был восьмибитовым и имел тактовую 4,7MHz  . Он даже взялся на спор показать мастеркласс в соревновании на скорость работы оконной библиотеки. В общем вечерами сидели и писали. Я на плюсах, правда с вкрапелениями на ASM, ибо уровень оптимизации тогдашних компиляторов был просто никакой, он на Си. Результат был как бы неожиданный - плюсовая работала быстрее  . Причина на самом деле проста - уже больно она красиво и хорошо ложилась она во все эти классы и иже с ними. Выигрыш был за счет лучшей системной оптимизации. На самом деле обе , библиотеки работали медленно  . Так что дальше начался этап писания на Си, но опираясь на понимание пришедшее с плюсов. Компиляторы с тех пор сделали громадный скачек так что СЕГОДНЯ откатываться на Си уже не пришлось-бы. Сегодня надо писать на C++, хотя я так и остался де-факто на Си. Но С++ подход к делу НАВСЕГДА остался со мной.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 7 2016, 08:50
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(esaulenka @ Apr 7 2016, 10:03)  При этом проекты не сказать, чтоб прямо сложные. Пара сотен килобайт исходников - это немного совсем... Цитата(zltigo @ Apr 7 2016, 10:35)  некую приблуду для которой требовалась, то, что я назвал, "оконной библиотекой" - то есть всякие окошки, текстовые естественно, но все же типа "Windows" Вот я и говорю, что проекты слишком малы для плюсов - я в основном ваяю различные интеллектуальные датчики и небольшие платы управления. До сотни килобайт еще не добирался  Вот начал делать один прибор уже с графическим дисплеем, там да, уже чувствуется необходимость увеличения абстракции верхнего уровня софта. Так что 100 КБайт кода - это по моим ощущением и есть примерная граница необходимости качественного скачка
|
|
|
|
|
Apr 8 2016, 05:31
|

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

|
QUOTE (Сергей Борщ @ Apr 7 2016, 16:49)  Я и мигалку светодиодов на плюсах пишу. В общем, с упомянутм мнением дядьки Шилдта в корне не согласен. +1. Дело не в объёме, а в подходе, в другом ощутительном состоянии, когда используешь С++. Кстати, это состояние можно испытывать и при сугубо сишном подходе (о чём выше сказано), но на плюсах это достигается проще, без помех.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Apr 8 2016, 08:45
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
может быть дядька Шилдт имел ввиду объектно-ориентированный подход, а не сам язык С++, который к объектно-ориентированному подходу достаточно перпендикулярен? Я не понимаю, что может мешать в программе класса "мигалка светодиодом" использовать перегрузку операторов: CODE void print(char const * string); void print(int number);
void test() { print("I = "); print(123); } // вместо дающего точно такой же выходной код сишного void print_string(char const * string); void print_number(int number);
void test() { print_string("I = "); print_number(123); } что мешает объявлять типы структур более короткой записью, без typedef: CODE struct a_t { int B; int C; }; a_t A;
// вместо дающего точно такой же выходной код сишного typedef struct { int B; int C; } a_t; a_t A; что мешает использовать шаблоны CODE void send(void const * from, size_t size);
template<typename T> inline void send(T & data) { send(&data, sizeof(data)); }
uint32_t A; uint8_t B; struct c_t { uint32_t A; uint8_t B; char Name[20]; } C;
void test() { send(A); send(B); send(C); }
// вместо дающего точно такой же выходной код сишного void test1() { send(&A, sizeof(A)); send(&B, sizeof(B)); send(&C, sizeof(C)); } что мешает использовать объявления структур внутри структур CODE struct config_t { struct module_a_t { .... }; struct module_b_t { .... }; module_a_t A; module_b_t B; } Config;
config::module_a_t * pModule_A_cfg = &Config.A; // вместо дающего точно такой же выходной код сишного typedef struct { .... } module_a_config_t; typedef struct { .... } module_b_config_t; typedef struct { module_a_config_t A; module_b_config_t B; } config_t; config_t Config;
module_a_config_t * pModule_A_cfg = &Config.A; что мешает использовать хотя бы простейшие объекты? CODE class a_t { public: void do_process(); private ... какие-то данные .... } a_t A, B; void test() { A.do_process(); B.do_process(); }
// вместо дающего точно такой же выходной код сишного typedef struct { ... какие-то данные .... } a_t; a_t A, B; void do_process(a_t * data);
void test() { do_process(&A); do_process(&B); } и таких примеров можно привести великое множество. Еще раз подчеркиваю - эти исходники дают абсолютно идентичный выходной код, но на С++ они короче, а значит их легче писать, в них труднее запутаться или допустить описку.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 8 2016, 10:28
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (ViKo @ Apr 8 2016, 11:00)  По-моему, в С так же можно использовать структуры, как и в С++. Покажите, как сделать такое: CODE struct config_t { struct module_a_t { .... }; struct module_b_t { .... }; module_a_t A; module_b_t B; } Config; Как это делается в Сях я показал, там больше писанины и нет сокрытия имен. QUOTE (ViKo @ Apr 8 2016, 11:00)  Из приведенных выше примеров привлекает полиморфизм. В приведенных выше примерах полиморфизма не было. Полиморфизм - это уже объектно-ориентированное программирование. QUOTE (ViKo @ Apr 8 2016, 11:00)  А до классов надо еще дорасти. У меня сотни функций, в какие объекты их пихать? Пихайте куда угодно (сколько информации в вопросе - столько и в ответе). Ваши функции не используют данные? Если используют - имеет смысл их логически объединить. функция + данные - это уже класс. а если несколько функций используют некоторую общую часть данных - напрашивается структура классов, где базовый работает с общей частью данных, а наследники - с общими данными через базовый класс и со своими личными данными - каждый по-своему. P.S. Если кто-то смотрел исходник openOCD - там полиморфизм реализован на чистых Сях. Это тихий ужас и закат солнца вручную.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 8 2016, 11:47
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (ViKo @ Apr 8 2016, 14:33)  А как называется свойство, когда функции с одинаковым именем работают с разными типами данных? Перегрузка функций. QUOTE (Сергей Борщ @ Apr 8 2016, 13:28)  Покажите, как сделать такое: CODE struct config_t { struct module_a_t { .... }; struct module_b_t { .... }; module_a_t A; module_b_t B; } Config; Так: CODE typedef struct config_t { struct { .... }A; struct { .... }B; } Config; QUOTE в Сях я показал, там больше писанины и нет сокрытия имен. Писанины в Сях оказалось меньше, а имена вообще отсутствуют за ненадобностью  .
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 8 2016, 12:03
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(Сергей Борщ @ Apr 8 2016, 11:45)  может быть дядька Шилдт имел ввиду объектно-ориентированный подход, а не сам язык С++, который к объектно-ориентированному подходу достаточно перпендикулярен? Я не понимаю, что может мешать в программе класса "мигалка светодиодом" использовать перегрузку операторов: что мешает объявлять типы структур более короткой записью, без typedef: что мешает использовать шаблоны что мешает использовать объявления структур внутри структур что мешает использовать хотя бы простейшие объекты?
и таких примеров можно привести великое множество. Еще раз подчеркиваю - эти исходники дают абсолютно идентичный выходной код, но на С++ они короче, а значит их легче писать, в них труднее запутаться или допустить описку. Тут я могу ответить только за себя - применять эти небольшие улучшения/расширения си, конечно можно, но я не вижу качественного улучшения. Поэтому и не применяю, тем более что накопилось много долгоиграющих проектов на разных МК под разными компиляторами, которые периодически нужно подкручивать и кидать куски кода туда-сюда. ANSI C поддерживает весь зоопарк применяемых мною инстументов, а вот плюсы - увы... Тем более, что ошибки/опечатки в аналогах всех вышеупомянутых улучшений хорошо отлавливаются компиляторами и тут проблем нет. А применение объектно-ориентированного подхода это уже отдельный вопрос и к вышеприведенным примерам отношения не имеющий, и на маленьких проектах ИМХО себя не оправдывающий.
|
|
|
|
|
Apr 8 2016, 13:26
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Сергей Борщ @ Apr 8 2016, 15:52)  И как теперь объявить указатель на структуру А? Не понял. Ты же хотел скрыть имена? Вот они и "скрыты". И вообще, что такое указатель на струкруру внутри структуры без использования наружной структуры? На кой он может быть нужен? Можешь написать на базе своего-же сишного примера, для чего это такое? В чем цимус: a = &c.A; a->x; перед s = &c; s->A.x; Тем более, что ценой нескольких слов typedef в хидре можно и в Си так-же получать доступ. Только вот от паковки структуры с таким доступом будет снос крыши. P.S. Если бы С++ структуры давали хоть сколь-нибудь существенное преимущество перед возможностями С99, то я бы при своей любви к описанию данных, уже точно писал на С++.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 8 2016, 13:45
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (zltigo @ Apr 8 2016, 15:26)  Не понял. Ты же хотел скрыть имена? Вот они и "скрыты". Они не то чтобы скрыты - это структуры безымянного типа. Плюсы позволяют иметь типы с именами, но при этом не засоряющие глобальную область видимости. QUOTE (zltigo @ Apr 8 2016, 15:26)  И вообще, что такое указатель на струкруру внутри структуры без использования наружной структуры? На кой он может быть нужен? Кто сказал, что без использования наружной? Выше был пример: есть наружная структура - глобальный конфиг системы. Она состоит из конфигов конкретных составляющих систему модулей. Работая с конфигом конкретного модуля удобно получить указатель (или ссылку, такого в голых Сях вообще нет) на конфиг конкретного модуля (выше показывал: config::module_a_t * pModule_A_cfg = &Config.A; или еще проще: auto pModule_A_cfg = &Config.A;). При этом в глобальной области видимости у меня только один тип - config_t. QUOTE (zltigo @ Apr 8 2016, 15:26)  Если бы С++ структуры давали хоть сколь-нибудь существенное преимущество перед возможностями С99, то я бы при своей любви к описанию данных, уже точно писал на С++. "Ты видишь суслика? А он есть!". Наследование, объявление типов и функций внутри структур - весьма существенное преимущество.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 8 2016, 14:11
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE "Ты видишь суслика? А он есть!". Наследование, объявление типов и функций внутри структур - весьма существенное преимущество. QUOTE (Сергей Борщ @ Apr 8 2016, 16:45)  При этом в глобальной области видимости у меня только один тип - config_t. Если ограничение глобальной видимости и неиспользование typedef это единственное практически извлекаемое из всего этого преимущество, то оно меня не слишком восхитило  .
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|