одинарный минус для 0x80000000 (подписан и не подписан) - PullRequest
2 голосов
/ 28 февраля 2012

В черновике n3337.pdf, 5.3.1.8, указывается, что:

Операнд унарного оператора - должен иметь арифметический или неисчисляемый тип перечисления, а результатом является отрицание его операнда,Интегральное продвижение выполняется для целочисленных или перечислимых операндов.Отрицательное значение беззнаковой величины вычисляется путем вычитания ее значения из 2 where, где n - количество битов в повышенном операнде.Тип результата - это тип повышенного операнда.

В некоторых случаях этого достаточно.Предположим, что unsigned int имеет ширину 32 бита, тогда (-(0x80000000u)) == 0x80000000u, не так ли?

Тем не менее, я ничего не могу найти про унарный минус на беззнаковых 0x80000000.Кроме того, черновик стандарта C99 n1336.pdf, 6.5.3.3, похоже, ничего не говорит об этом:

Результат унарного оператора является отрицательным по отношению к его (повышенному) операнду.Целочисленные преобразования выполняются над операндом, и результат имеет продвинутый тип.

ОБНОВЛЕНИЕ2: Предположим, что unsigned int имеет ширину 32 бита.Итак, вопрос: как насчет унарного минуса в C (со знаком и без знака) и унарного минуса в C ++ (только со знаком)?

UPDATE1: как поведение во время выполнения, так и поведение во время компиляции (то есть константа-интересны.

(связано: Почему abs (0x80000000) == 0x80000000? )

Ответы [ 2 ]

5 голосов
/ 28 февраля 2012

Для вашего вопроса важная часть цитаты, которую вы включили, такова:

Отрицание числа без знака вычисляется путем вычитания его значения из 2ⁿ, где n - числобиты в продвинутом операнде.

Итак, чтобы узнать значение -0x80000000u, нам нужно знать n, количество бит в типе 0x80000000u.Это как минимум 32, но это все, что мы знаем (без дополнительной информации о размерах типов в вашей реализации).Учитывая некоторые значения n, мы можем вычислить, каков будет результат:

n   | -0x80000000u 
----+--------------
32  | 0x80000000
33  | 0x180000000
34  | 0x380000000
48  | 0xFFFF80000000
64  | 0xFFFFFFFF80000000

(Например, реализация, в которой unsigned int равен 16 битам, а unsigned long равен 64 битам, будет иметь n из 64).


C99 имеет эквивалентную формулировку, скрытую в §6.2.5 Типы p9:

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

Результат унарного оператора -для беззнакового операнда, отличного от нуля, это правило всегда будет отслеживаться.

При 32-битном int тип 0x80000000 будет unsigned int, независимо от отсутствия uсуффикс, поэтому результатом все равно будет значение 0x80000000 с типом unsigned int.

Если вместо этого вы используете десятичную константу 2147483648, она будет иметь тип long, и вычисление будет подписано.Результатом будет значение -2147483648 с типом long.

2 голосов
/ 28 февраля 2012

В n1336, 6.3.1.3 Целые числа со знаком и без знака, параграф 2 определяет преобразование в целое число без знака:

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

То есть для 32-разрядного целого без знака, -0x80000000u==-0x80000000 + 0x100000000==0x80000000u.

...