Павел_Б 0 Posted September 16, 2020 · Report post Здравствуйте. Читаю чужой код и появился вопрос - что делает такая процедура: ___ A=0; cnt=0; do { delay_ms(200); cnt++; } while ((A!=1) && (cnt!=200)); ___ Я так понимаю что если программа дойдёт до этого места то будет ожидать пока А не станет равно 1 или не пройдёт 40 секунд. Если А станет равно 1 то программа пойдёт дальше или если cnt станет равно 200 то программа тоже пойдёт дальше. Правильно ли я понимаю этот кусок кода? Спасибо! Quote Ответить с цитированием Share this post Link to post Share on other sites
Forger 0 Posted September 16, 2020 · Report post Судя по коду, А всегда тут 0, поэтому завершение цикла наступит только по второму условию Скорее всего оптимизатор компилятора это увидит и сам автоматом выпилит условие A!=1, как бесплезное. Но это при условии если A объявлена как локальная переменная. Тоже самое касается cnt, она не должна быть доступна извне, например, из прерываний, иначе поведение кода неоднозначно. Quote Ответить с цитированием Share this post Link to post Share on other sites
aaarrr 0 Posted September 16, 2020 · Report post 1 minute ago, Forger said: Судя по коду, А всегда тут 0 Из приведенного фрагмента это никак не следует. Хотя код и ужасный, конечно. Quote Ответить с цитированием Share this post Link to post Share on other sites
Forger 0 Posted September 16, 2020 · Report post 1 minute ago, aaarrr said: код и ужасный Нынче это в тренде :) Quote Ответить с цитированием Share this post Link to post Share on other sites
Павел_Б 0 Posted September 16, 2020 (edited) · Report post А - глобальная - то есть значение на 1 может измениться в другой подпрограмме по прерыванию. cnt - локальная. Как мне исправить код чтобы программа ждала пока А не станет 1 в другой подпрограмме или не пройдёт 40 секунд. То есть программа должна пойти дальше в зависимости от одного из условий. Спасибо! Edited September 16, 2020 by Павел_Б Quote Ответить с цитированием Share this post Link to post Share on other sites
Forger 0 Posted September 16, 2020 · Report post 27 minutes ago, Павел_Б said: Как мне исправить код чтобы программа ждала пока А не станет 1 в другой подпрограмме или не пройдёт 40 секунд. ничего не надо исправлять, и так сойдет ;) Quote Ответить с цитированием Share this post Link to post Share on other sites
Сергей Борщ 0 Posted September 16, 2020 · Report post 49 минут назад, Павел_Б сказал: А - глобальная Какие еще у нее есть свойства? Присутствует ли в ее объявлении квалификатор volatile? Quote Ответить с цитированием Share this post Link to post Share on other sites
Павел_Б 0 Posted September 16, 2020 · Report post 12 minutes ago, Сергей Борщ said: Какие еще у нее есть свойства? Присутствует ли в ее объявлении квалификатор volatile? bit A; // - это глобальная битовая переменная 35 minutes ago, Forger said: ничего не надо исправлять, и так сойдет ;) Спасибо! Quote Ответить с цитированием Share this post Link to post Share on other sites
haker_fox 0 Posted September 16, 2020 · Report post 33 minutes ago, Павел_Б said: bit A; // - это глобальная битовая переменная Неужто старый, добрый CodeVision? Quote Ответить с цитированием Share this post Link to post Share on other sites
Павел_Б 0 Posted September 16, 2020 · Report post Just now, haker_fox said: Неужто старый, добрый CodeVision? Он родимый ;) Quote Ответить с цитированием Share this post Link to post Share on other sites
Сергей Борщ 0 Posted September 16, 2020 · Report post Тогда я пас. Как известно, CV - компилятор с "языка, похожего на C". Если бы программа была написана на C, то без volatile компилятор, зная содержимое delay_ms() (т.е. зная, что A в ней не меняется), имел бы полное право выкинуть проверку (A!=1) из цикла, так как прямо перед циклом A = 0 и в цикле A не меняется. Quote Ответить с цитированием Share this post Link to post Share on other sites
Павел_Б 0 Posted September 17, 2020 · Report post Всем большое спасибо! Quote Ответить с цитированием Share this post Link to post Share on other sites
Darth Vader 0 Posted September 17, 2020 · Report post Раз уж у темы столь всеобъемлющее название, кину и я свой вопрос сюда. Насколько идеологически правилен такого рода код: volatile char A; void Foo(const char *p); int main(void){ Foo(&A); } Компилятор выдает предупреждение о несоответствии типов параметра функции в описании и вызове. Погасить его можно применив явное приведение типа аргумента при передаче его в функцию: Foo((char*)(&A)); Что идеологически более правильно - забить на предупреждение компилятора, или явно привести тип аргумента, откинув тем самым из него volatile? Актуально для многих библиотечных функций, принимающих указатели. Например, memcpy, memcmp и т.п. Проблема возникает именно с указателями на volatile-переменные. Случайно наткнулся и задумался, как бы это красиво и правильно решить. Quote Ответить с цитированием Share this post Link to post Share on other sites
Сергей Борщ 0 Posted September 17, 2020 · Report post 2 часа назад, Darth Vader сказал: или явно привести тип аргумента, откинув тем самым из него volatile? Если при использовании этой конкретной функции volatile ни на что не влияет - привести явно. Попробую объяснить: если вы передаете в, скажем, memcmp() массив volatile - переменных, и обращение к одним переменным не влияет на другие, т.е. допустимо обращение к элементам в любом порядке - то можно делать приведение типа. А вот если порядок влияет (скажем, вы передаете структуру какой-то периферии, где чтение регистра данных сбрасывает флаги и вам обязательно нужно прочитать сначала регистр флагов и только потом регистр данных) - то надо писать свою реализацию функции, приннимающую volatile-аргумент и обращающуюся к данным в нужном порядке. В любом случае забивать на предупреждения ни в коем случае нельзя - если ваша программа при каждой компиляции выдает предупреждения - вам просто надоест их читать и когда появится действительно важное предупреждение - вы его банально пропустите в этом шуме. 2 часа назад, Darth Vader сказал: и задумался, как бы это красиво и правильно решить Переключить компилятор в режим C++ и переопределить функцию для volatile-аргумента. Пусть это явное приведение типа будет спрятано внутри переопределенной функции, а компилятор сам подставит вызов той или другой в зависимости от типа аргумента: void Foo(char const *p); inline void Foo(char const volatile *p) { Foo(const_cast<char const *>(p)); Quote Ответить с цитированием Share this post Link to post Share on other sites
artemkad 0 Posted September 17, 2020 · Report post 2 часа назад, Darth Vader сказал: Компилятор выдает предупреждение о несоответствии типов параметра функции в описании и вызове. Погасить его можно применив явное приведение типа аргумента при передаче его в функцию: Foo((char*)(&A)); Идеологически переменная объявлена как "может поменяться в любой момент сама", а аргумент как - "никто кроме функции её не поменяет". Естественно, исходя из этих объявлений компилятор и создает код. Потому и предупреждает, что возможно не зная о volatile функция вообще стала пустой. Quote Ответить с цитированием Share this post Link to post Share on other sites