2013-11-29 7 views
0

Если х беззнаковый типа INT есть разница в этих утверждениях:Унарного отрицания целого числа без знака 4

return (x & 7); 

и

return (-x & 7); 

Я понимаю, отрицая беззнаковое значение дают значение max_int - value , Но существует ли разница в возвращаемом значении (т. Е. Истинное/ложное) среди вышеупомянутых двух операторов в любых конкретных граничных условиях ИЛИ они оба одинаковы функционально?

+1

Вы могли бы проверить себя довольно легко, не так ли? В общем, да, есть разница. –

ответ

4

код теста:

#include <stdio.h> 

static unsigned neg7(unsigned x) { return -x & 7; } 

static unsigned pos7(unsigned x) { return +x & 7; } 

int main(void) 
{ 
    for (unsigned i = 0; i < 8; i++) 
     printf("%u: pos %u; neg %u\n", i, pos7(i), neg7(i)); 
    return 0; 
} 

Результаты тестов:

0: pos 0; neg 0 
1: pos 1; neg 7 
2: pos 2; neg 6 
3: pos 3; neg 5 
4: pos 4; neg 4 
5: pos 5; neg 3 
6: pos 6; neg 2 
7: pos 7; neg 1 

для конкретного случая 4 (а также 0), не существует различия; для других значений существует разница. Вы можете расширить диапазон ввода, но выходы будут создавать один и тот же шаблон.

+1

Это также показывает, что, вопреки тому, что считает ОП, оператор '&' does not not возвращает логическое значение true/false. – usr2564301

+0

Просто любопытно ... почему вы отметили эти функции как «статические»? – RastaJedi

+0

@RastaJedi: потому что они не используются вне этого файла, и нет заголовка, чтобы объявлять их, и параметры компиляции, которые я использую ('gcc -O3 -g -std = c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror ... ') требуют объявления для нестатических функций, отличных от' main() '. Вероятно, я добавлю 'inline' в наши дни (а' static inline' - куча, которую легче понять, чем альтернативы). –

1

Во-первых, отрицание значения unsigned int производит UINT_MAX - original_value + 1. (Например, 0 остается 0 при отрицании). Альтернативный способ описания отрицания - полная инверсия всех бит, за которыми следует приращение.

Непонятно, почему вы даже задали этот вопрос, так как очевидно, что в основном самый первый пример, который приходит на ум - значение unsigned int1 - уже производит разные результаты в вашем выражении. 1u & 7 есть 1, в то время как -1u & 7 есть 7. Вы имели в виду что-то еще, случайно?

1

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

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

Давайте посмотрим на этих двух случаях:

Во-первых, если три младших бит равны нулю (для false эквивалент). Инвертирование дает все, приращение снова приводит к нулю. Четвертый и более значимые бит могут отличаться, но они не влияют на младшие значащие биты, и они не влияют на результат, поскольку они замаскированы. Так что это остается.

Во-вторых, если три младших разряда не все равны нулю (для эквивалента true). Единственный способ, которым это может измениться на false, - это когда операция инкремента оставляет их в нуле, что может произойти только в том случае, если они были все раньше, что, в свою очередь, могло произойти только в том случае, если все они были нулями перед инверсией. Этого не может быть, так как это первый случай. Опять же, более значимые биты не влияют на три младших бита, и они маскируются. Поэтому результат не меняется.

Но опять же, это работает только тогда, когда вызывающий объект учитывает только значение истины (все биты нуль/не все биты нуль), а когда маска допускает диапазон бит, начиная с наименее значимого без пробела.

+0

Во время чтения я не знаю, было ли это просто очень подробно, но похоже, что вы сделали его более сложным, чем на самом деле, но я все еще мог следить, и это все еще отличный ответ, +1. В значительной степени это формулировка для ответа и описание ответа Джонатана Леффлера. – RastaJedi

Смежные вопросы