неверное значение переменной после битового сдвига и добавления в c

#c

#c

Вопрос:

У меня есть этот код, который в основном принимает два целых числа, сдвигает каждое и добавляет их. Однако после добавления я получил неверное значение.

Я нашел выход из этого (то есть путем сохранения сдвинутых значений в новых беззнаковых переменных int и добавления двух), но я хочу понять, почему это не сработало:

 void change(uint8_t in[3], uint16_t out[2]){
    out[0] = in[0]<<2   in[1]>>2;
    printf("%un",in[0]<<2 ); // outputs 48  --- correct
    printf("%un",in[1]>>2 ); // output 1 --- correct
    printf("%un",out[0] ); // output 768 --- wrong, I expected 49
}

int main(int argc, char const *argv[])
{
    uint8_t in[3] = {12,6,9};
    uint16_t out[2];
    change(in,out);
    return 0;
}
 

Комментарии:

1. используйте скобки out[0] = (in[0]<<2) (in[1]>>2);

2. puts("hello, operator precedence");

3. @Vaibhav , это решило мою проблему. большое, очень большое спасибо.

Ответ №1:

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

 out[0] = (in[0]<<2)   (in[1]>>2);
 

Без круглых скобок оно оценивается как

 out[0] = in[0] << (2   in[1]) >> 2;
 

GCC показывает это предупреждение при компиляции вашего кода с предупреждениями о:

 test.c:5:23: warning: suggest parentheses around ‘ ’ inside ‘<<’ [-Wparentheses]
     out[0] = in[0]<<2   in[1]>>2;
                       ^
 

Это пример того, почему мы всегда должны обращать внимание на предупреждения компилятора.

Комментарии:

1. @Babydesta это предупреждение, а не ошибка. Пожалуйста, проверьте документацию вашего компилятора о том, как включить предупреждения. Для GCC я всегда использую -Wall -Wextra .