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