Да, я заранее проверил что 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 - намёк