2016-03-07 15 views
0

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

Общая идея заключается в том, что если бит знака равен 0, просто возвращаем число, поскольку оно уже находится в двух дополнениях, если оно одно, но тогда я хочу установить его в 0 перед инвертированием всех бит с помощью оператора ~, а затем добавить 1.

заранее спасибо

+2

Пожалуйста, покажите свое усилие до сих пор. – Marievi

+1

Хммм ... если последний бит в подписанной переменной равен 1, тогда 'x <0' должно быть истинным ... вам не нужно проверять конкретный бит. – Myst

+0

Для этого вы можете использовать '&'. '0b01111111 & bits', таким образом, результат будет иметь восьмой бит, равный 0, независимо. – yeyo

ответ

1

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

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

uint8_t x = (some value) 
if (x & (1 << 7)) { 
    printf("sign bit set\n"); 
    x = (uint8_t)((~(x & (0x7F))) & 0xFF) + 1; 
    printf("converted value: %02X\n", x); 
} 

Тогда вы можете добавить этот номер к любому другому обычно.

+1

Или просто 'int8_t result = x & 0x7F; if (x & (1 << 7)) result = -result;' Более читаемый и потенциально немного быстрее. – Lundin

1

Если предположить, что ваш компьютер/компилятор использует двоичное дополнение (почти наверняка случай) и при условии, что вы хотите, чтобы результат в виде дополнения до двух.

Используйте знак uint8_t, чтобы держать знак и величину величины.

Чтобы проверить, установлен ли бит, используйте побитовый оператор И & вместе с битовой маской, соответствующей значению msb. Чтобы получить битовую маску, соответствующую бит n, сдвиньте влево значение 1 n раз. В C-коде:

#define SIGN (1 << 7) 

uint8_t sm = ...; 
if(sm & SIGN)  // if non-zero, then the SIGN bit is set 
{ 
} 
else    // it was zero, the SIGN bit is not set 
{ 
} 

Чтобы сделать фактическое преобразование, существует несколько способов. Я бы просто маскировать и скопировать соответствующие части числа, снова побитового И:

#define MAGNITUDE 0x7F 

int8_t magnitude = sm & MAGNITUDE; // variable magnitude is two's compl. 

EDIT полное решение (так как кто-то уже писал один):

#define SIGN (1 << 7) 
#define MAGNITUDE 0x7F 

uint8_t sm = ...; 
int8_t twos_compl = sm & MAGNITUDE; 

if(sm & SIGN)  // if non-zero, then the SIGN bit is set 
{ 
    twos_compl = -twos_compl; 
} 

int8_t x = ...; // some other number in two's complement 
int16_t result = twos_compl + x; 

В качестве побочной заметки будьте очень осторожны при смешивании оператора ~ с малыми целыми типами, поскольку он выполняет неявное целочисленное продвижение. Например, uint8_t x = 1, а затем ~my_uint8 дает вам 0xFFFFFFFE (32-битная система), а не 0xFE, как вы могли ожидать.

Для вышеуказанной задачи нет необходимости использовать ~.