Подтвердить что ты не робот

C: унарный минус поведение оператора с неподписанными операндами

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

Стандарт С++ 2003 (да, С++, нести меня за несколько строк) говорит в 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.

Однако стандарт 1999 C не содержит такого явного утверждения и не дает четкого определения унарного поведения ни в 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.

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

4b9b3361

Ответ 1

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

Ответ 2

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

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.

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

Ответ 3

Поведение унарного оператора минус на неподписанных операндах не имеет никакого отношения к тому, использует ли машина арифметику с двумя номерами с подписанными числами. Вместо этого при задании 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 уступая нулю.