C: поведение унарного минуса с неподписанными операндами - PullRequest
30 голосов
/ 06 ноября 2011

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

Стандарт C ++ 2003 года (да, C ++, терпите меня занесколько строк) в 5.3.1c7 сказано: The negative of an unsigned quantity is computed by subtracting its value from 2^n, where n is the number of bits in the promoted operand.

Однако в стандарте C 1999 года такого явного утверждения не содержится и не дается четкого определения унарного поведения ни в 6.5.3.3c1,3.ни в 6.5c4.В последнем написано Some operators (the unary operator ~, and the binary operators <<, >>, &, ^, and |, ...) ... return values that depend on the internal representations of integers, and have implementation-defined and undefined aspects for signed types.), что исключает унарный минус, и вещи кажутся неопределенными.

Этот более ранний вопрос относится к книге K & R ANSI C, раздел A.7.4.5что говорит The negative of an unsigned quantity is computed by subtracting the promoted value from the largest value of the promoted type and adding one.

Каким будет стандарт С 1999 года, эквивалентный приведенной выше цитате из книги?

6.2.5c9 говорит: A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

ЭтоЭто?Или что-то еще мне не хватает?

Ответы [ 3 ]

16 голосов
/ 06 ноября 2011

Да, 6.2.5c9 - это именно тот абзац, который вы искали.

6 голосов
/ 22 июня 2015

Поведение унарного оператора минус на беззнаковых операндах не имеет ничего общего с тем, использует ли машина арифметику с двумя дополнительными числами со знаковыми числами. Вместо этого, учитывая unsigned int x,y;, оператор y=-x; заставит y получить любое значение, которое он должен хранить, чтобы x+y стало равным нулю. Если x равно нулю, y также будет равно нулю. Для любого другого значения x это будет UINT_MAX-x+1, и в этом случае арифметическое значение x+y будет UINT_MAX+1+(y-y), которое при присвоении unsigned integer будет вычитать UINT_MAX+1 из него, уступая нулю.

3 голосов
/ 06 ноября 2011

В каждой известной мне реализации отрицание рассчитывается как дополнение к двум ...

int a = 12;
int b = -a;
int c = ~a + 1;
assert(b == c);

... так что на самом деле нет никакой физической разницы между знаком с отрицательным знаком и "отрицательные целые числа без знака - единственная разница в том, как они интерпретируются .

Так что в этом примере ...

unsigned a = 12;
unsigned b = -a;
int c = -a;

... bи c будут содержать одинаковые биты.Единственное отличие состоит в том, что b интерпретируется как 2 ^ 32-12 (или 2 ^ 64-12), а c интерпретируется как «нормальный» -12.

Таким образом, рассчитывается отрицательныйточно так же, независимо от «подписи», и приведение между неподписанным и подписанным фактически не допускается (и никогда не может вызвать переполнение в том смысле, что некоторые биты должны быть «обрезаны»).

...