Да, я заранее проверил что 2 == ~0xFFFD, но как вы думаете, что вернет cmp() ? А cmp() возвращает всегда false. Причина в неявном и непонятном приведении типа. ~getb() cстановится int'ом, хотя сам getb() был uint16. Если переписать вот так
Это баги компилятора, я уже много раз с таким сталкивался, по этому, я не ленюсь всегда явно приводить типы, иногда даже в самых неожиданных местах, а особенно в тернарных операциях. Ну и да, код от этого выглядит чуток некрасиво, зато явно видно что подразумевается и что ожидается. У компиляторов куча багов, так что лично я всегда предпочитаю исходить из предпосылки, что компиляторы не идеальны и насуют кАстылей.
Мне кажется, что это не баг - и Visual Studio и IAR ведут себя абсолютно одинаково. Одинаковый баг в обоих компиляторах выглядит довольно подозрительно.
на електроникс.ру, эдак в 2007м, мы обсуждали много таких моментов, и их было оооой как много. там даже ребята олдовые на спор приводили куски кода для воспроизведения подобных багов, забавная была тема. в результате, все как один пришли к такому же выводу что я описал.
в принципе рассматривая ~ как обычную функцию(очевидно у неё будут на входе и выходе int) или пусть даже как asm команду - поведение по-моему логичное, но к сожалению архитектуро-зависимое
На ru_embedded разобрались. Ошибся, как не странно, я. Как оказывается, при арифметических операциях, компилятор приводит все типы, меньше чем int к int'у (ну, или если тип не может вместиться в int, то к unsigned int'у). И только потом выполняется арифметическая операция.
Вот тут статья, которая подробно объясняет что и как.
ПОсмотрите пожалуйста код, как думаете , как можно сделать красивее? Это фунция на вход получает значение счетчика таймера на котором энодер, выдает адаптированное значение ,приращение значение зависит от скорости вращения энкодера.
uint16_t smart_encoder(uint16_t iner){ static char i; static uint16_t tmp=0, result=0; static int accum =0; int diff = ((((int)tmp)<<16)-(((int)iner)<<16))>>16; //эта строчка работает правильно, но сама не красива, может кто знает решение? //int16_t diff = (int16_t)tmp-(int16_t)iner; //эта строчка не работает, при переходе iner ч 0 в 0xFFFF и назад получается ерунда if (diff>0) accum += diff; else accum -= diff; tmp=iner; if (-diff*(accum)<=(int)result) result+=diff*(accum); else result=0; //accum>>=(1); accum>>=(++i&1); return result; }
1 - уже сама по себе декларация переменной и тут же присваивание значения через какие то мат операции не есть "гудвэй" (такое на ура прокатывает в С++, но не желательно в С, так как компилеры часто лажают). Однако для GCC такое поведение странное, чет мне кажется это с подачи стмовских патчей 2 - int diff - намёк