Перейти к содержанию
    

Здравствуйте.

Читаю чужой код и появился вопрос - что делает такая процедура:

___

A=0;
cnt=0;
do {
delay_ms(200);
cnt++;
}
while   ((A!=1) && (cnt!=200));

___

Я так понимаю что если программа дойдёт до этого места то будет ожидать пока А не станет равно 1 или не пройдёт 40 секунд.

Если А станет равно 1 то программа пойдёт дальше или если cnt станет равно 200 то программа тоже пойдёт дальше.

Правильно ли я понимаю этот кусок кода?

Спасибо!

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Судя по коду, А всегда тут 0, поэтому завершение цикла наступит только по второму условию

Скорее всего оптимизатор компилятора это увидит и сам автоматом выпилит условие A!=1, как бесплезное.

Но это при условии если A объявлена как локальная переменная.

Тоже самое касается cnt, она не должна быть доступна извне, например, из прерываний, иначе поведение кода неоднозначно.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, Forger said:

Судя по коду, А всегда тут 0

Из приведенного фрагмента это никак не следует. Хотя код и ужасный, конечно.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А - глобальная - то есть значение на 1 может измениться в другой подпрограмме по прерыванию.

cnt - локальная.

Как мне исправить код чтобы программа ждала пока А не станет 1 в другой подпрограмме или не пройдёт 40 секунд.

То есть программа должна пойти дальше в зависимости от одного из условий. 

Спасибо!

Изменено пользователем Павел_Б

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

27 minutes ago, Павел_Б said:

Как мне исправить код чтобы программа ждала пока А не станет 1 в другой подпрограмме или не пройдёт 40 секунд.

ничего не надо исправлять, и так сойдет ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

49 минут назад, Павел_Б сказал:

А - глобальная

Какие еще у нее есть свойства? Присутствует ли в ее объявлении квалификатор volatile?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 minutes ago, Сергей Борщ said:

Какие еще у нее есть свойства? Присутствует ли в ее объявлении квалификатор volatile?

bit A;                  // - это глобальная битовая переменная

 

35 minutes ago, Forger said:

ничего не надо исправлять, и так сойдет ;)

Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

33 minutes ago, Павел_Б said:

bit A;                  // - это глобальная битовая переменная

Неужто старый, добрый CodeVision?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда я пас. Как известно, CV - компилятор с "языка, похожего на C". Если бы программа была написана на C, то без volatile компилятор, зная содержимое delay_ms() (т.е. зная, что A в ней не меняется), имел бы полное право выкинуть проверку (A!=1) из цикла, так как прямо перед циклом A = 0 и в цикле A не меняется.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Раз уж у темы столь всеобъемлющее название, кину и я свой вопрос сюда.

Насколько идеологически правилен такого рода код:

volatile char A;
void Foo(const char *p);

int main(void){
  Foo(&A);
}

Компилятор выдает предупреждение о несоответствии типов параметра функции в описании и вызове. Погасить его можно применив явное приведение типа аргумента при передаче его в функцию: Foo((char*)(&A));

Что идеологически более правильно - забить на предупреждение компилятора, или явно привести тип аргумента, откинув тем самым из него volatile? Актуально для многих библиотечных функций, принимающих указатели. Например, memcpy, memcmp и т.п. Проблема возникает именно с указателями на volatile-переменные.

Случайно наткнулся и задумался, как бы это красиво и правильно решить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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));

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, Darth Vader сказал:

Компилятор выдает предупреждение о несоответствии типов параметра функции в описании и вызове. Погасить его можно применив явное приведение типа аргумента при передаче его в функцию: Foo((char*)(&A));

Идеологически переменная объявлена как "может поменяться в любой момент сама", а аргумент как - "никто кроме функции её не поменяет". Естественно, исходя из этих объявлений компилятор и создает код.  Потому и предупреждает, что  возможно не зная о volatile функция вообще стала пустой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...