C - Казалось бы, неподписанный int является расширением знака при сдвиге вправо?
Поэтому я пытался протестировать супер короткую функцию для получения целочисленного значения определенных битов от x до y из целого числа, но у меня возникли некоторые проблемы с происходящим расширением знака. Я попытался привести к unsigned int и затем переключиться с использованием unsigned int, но это, похоже, не работает. Код следующий:
#include <stdio.h>
int main()
{
int bo_bits = 2;
int tag_bits = 28;
int addr = 1;
unsigned int index = (unsigned int)addr;
index = index << tag_bits;
index = index >> bo_bits;
// at this point I would return (int)index;
return 0;
}
Я не понимаю, почему происходит расширение знака, так как я перешел только на целое число без знака. Я также запустил код, используя просто "addr", и использовал его как целое число без знака, но это также не изменило вывод.
Выходное значение для индекса равно 536870912, когда я запускаю функцию в gdb на компьютере с Linux и при компиляции в сети (теперь это кодирование), получаем значение 67108864.
Изменить: пару человек спросили, как я получил значение 536870912, я получил его, запустив GDB через обе точки останова и запустив команду p get_index(1)
из GDB. Фактический код следующий:
unsigned int index = (unsigned int)addr;
index = index << tag_bits;
index = index >> bo_bits;
return (int)index;
Спасибо за помощь!
1 ответ
536870912 равно 1 << 29, что означает, что оно не имеет ничего общего с расширением знака.
может быть, именно вы останавливаетесь в неправильном месте при отладке программы
вот что говорит стандарт c99 о сдвиге вправо. ( 6.5.7 Операции побитового сдвига)
Результатом E1 >> E2 является E1-сдвинутая вправо битовая позиция E2. Если E1 имеет тип без знака или если E1 имеет тип со знаком и неотрицательное значение, значение результата является неотъемлемой частью отношения E1 / 2^E2. Если E1 имеет тип со знаком и отрицательное значение, результирующее значение определяется реализацией.