A -- оператор в цикле while

Я кодирую на C на компиляторе IAR и имею два цикла while:

i= 5;
do {
    Task_sleep(1000);
}while(i-- && !Ready);

if (!Ready)
   {
      dprint("No ready response!");
      return false;
   }

А также

i= 5;
do {

    Task_sleep(1000);
    i--;
}while(i > 0 && !Ready);

if (!Ready)
       {
          dprint("No ready response!");
          return false;
       }

Первый пропустит цикл while, а второй работает правильно. Логическое значение «Готово» установлено в другом потоке. Первый цикл вернет false, а второй пройдет, поэтому для Ready не устанавливается значение true.

Я думаю, что компилятор не знает, как обрабатывать i-- в то время как и устанавливает для него значение false. Есть ли что-то еще, что может происходить? С моей настройкой я не могу выполнить код в отладке.

Изменить Добавлено в функции:

if(!Ready)
{
 dprint("No Ready responce!");
return false;
}

Проверено Ready как volatile, --i вместо i-- и удалено Ready. Все не удалось. Тестирование:

}while(((i--) > 0) && !Ready);

Все еще не удается, это должен быть компилятор IAR, который неправильно читает i-- и должен удалить операцию -- из функции while. Дайте мне знать, если у вас есть что-нибудь еще, что я могу попробовать, но я уверен, что закрою эту проблему.


c iar
person John.Majzner    schedule 27.04.2016    source источник
comment
В первом вы ни с чем не сравниваете свой i--, чтобы соответствовать второму, разве это не должно быть while(i-- > 0 && !Ready)?   -  person gmiley    schedule 28.04.2016
comment
@gmiley а? не подразумевается?   -  person Sourav Ghosh    schedule 28.04.2016
comment
@gmiley: нет. Что касается while, i-- оценивается либо как true (когда i != 0), либо как false (когда i = 0) — оба проверяются до фактического уменьшения.   -  person Jongware    schedule 28.04.2016
comment
С чего бы это? Все, что делает i--, это уменьшает переменную i на 1.   -  person gmiley    schedule 28.04.2016
comment
цикл do всегда выполняется хотя бы один раз.. вы говорите, что даже не получаете ни одного Task_sleep() с первым циклом?   -  person yano    schedule 28.04.2016
comment
@gmiley: так по-вашему, это i = 5; do { printf ("%d\n", i); } while (i--); не сработает? (Осторожно: я проверял это.)   -  person Jongware    schedule 28.04.2016
comment
поместите printf в первый цикл перед сном. Держу пари, что-нибудь распечатают.   -  person bruceg    schedule 28.04.2016
comment
Является ли переменная Ready изменчивой? Если нет, компилятор может закоротить это.   -  person Jongware    schedule 28.04.2016
comment
Неважно, это правильно, любое ненулевое значение истинно, ноль ложно. Я просто всегда явно печатаю свои сравнения. Единственная альтернатива состоит в том, что Ready по-прежнему устанавливается на true. Попробуйте распечатать текущее значение Ready в цикле.   -  person gmiley    schedule 28.04.2016
comment
Кроме того, вы можете пометить вопрос тегом [iar] на случай, если это что-то странное с их компилятором.   -  person bruceg    schedule 28.04.2016
comment
Я подозреваю, что настоящая проблема здесь не связана с i, а связана с Ready. Полностью согласен с тем, что сказал @RadLexus. Это также может быть какое-то состояние гонки между настройкой потока Ready и тем, который здесь читает его ... недостаточно кода, чтобы сказать.   -  person yano    schedule 28.04.2016
comment
Я думаю, что он входит в цикл один раз, но похоже, что для i-- устанавливается значение false, когда i = 5. Я согласен, что i-- › 0 - это правильный способ написать это для первой функции, но я не был уверен если это подразумевалось или зависит от компилятора, как он это читает.   -  person John.Majzner    schedule 28.04.2016
comment
Вы всегда можете просто while (i--) if (!READY) Task_sleep (1000);   -  person David C. Rankin    schedule 28.04.2016
comment
Я бы полностью удалил Ready из условия while, тогда вы можете играть с i сколько хотите. Попробуйте i--, --i в условиях, уменьшите i в цикле, что угодно. Это должно сказать вам, действительно ли это проблема с i или Ready бросает вам гаечный ключ   -  person yano    schedule 28.04.2016
comment
@John.Majzner - НЕ удаляйте части своих вопросов. Можно сколько угодно ДОБАВЛЯТЬ к вашему вопросу, но не удалять. Это делает все предыдущие ответы вырванными из контекста и бесполезными для других.   -  person David C. Rankin    schedule 28.04.2016
comment
Показать сборку, соответствующую каждому случаю   -  person M.M    schedule 28.04.2016
comment
код (правильно) инициализирует переменную Ready значением 0/false перед входом в опубликованный цикл?   -  person user3629249    schedule 28.04.2016
comment
Какой процессор вы используете? Для MSP430 и AVR инструменты IAR предоставляют встроенный __delay_cycles() код вставки, ожидающий заданное количество циклов. Этот код не будет затронут компилятором.   -  person Lindydancer    schedule 03.06.2016


Ответы (3)


Вы путаете операторы постдекремента с операторами предварительного декремента. Два оператора разные. И i--, и --i будут уменьшать i. Но их значения разные. Значение i--, постдекрементного оператора, является старым значением i. Значение --i, преддекрементного оператора, является новым значением i.

person Tom Karzes    schedule 27.04.2016
comment
Я не знаю, что означает OP. Первый пропустит цикл while, но если i начинается с 5, он должен получить некоторый цикл независимо от используемого оператора post/pre-decrement. Конечно, цикл также зависит от Ready... - person yano; 28.04.2016
comment
Ready устанавливается в true через ~3 с. В первом цикле похоже, что он ждет 1 с, а затем продолжает работать. Во втором цикле он ждет 3 с, а затем движется дальше. Ready имеет значение false в первой функции, что приводит к сбою позже в потоке. - person John.Majzner; 28.04.2016

Ваш первый код:

do {
    Task_sleep(1000);
}while(i-- && !Ready);

Эквивалентно этому:

int condition;
TOP:
Task_sleep(1000);
condition = (i != 0 && !Ready);
i = i - 1;
if (condition)
    goto TOP

Ваш второй код:

do {

    Task_sleep(1000);
    i--;
}while(i > 0 && !Ready);

эквивалентно этому:

int condition;
TOP:
Task_sleep(1000);
i = i - 1;
condition = (i > 0 && !Ready);
if (condition) goto TOP;

Петли разные. i уменьшается в разное время по сравнению со временем оценки условия, и сравнение i внутри условия отличается.

person NovaDenizen    schedule 28.04.2016

Может быть, вы можете попробовать использовать ключевое слово volatile для уточнения переменной i в первой версии. Я столкнулся с подобной проблемой на прошлой неделе.

person Xinyu Pan    schedule 27.04.2016