Побитовое отрицание беззнакового символа

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

В разделе 6.5.3.3 говорится, что:

Целочисленные продвижения выполняются над операндом, и результат имеет продвигаемый тип. Если продвигаемый тип является типом без знака, выражение ~E эквивалентно максимальному значению, представленному в этом типе, за вычетом E.

Правильно ли я понимаю, когда я говорю это, это означает, что:

unsigned int ui = ~ (unsigned char) ~0; // ui is now 0xFF00.

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

unsigned char uc = 0;
unsigned char ucInverted = ~0;

if( ~uc == ~0 )              // True, obviously
if( ~ucInverted == ~(~0) )   // False as it evaluates to: 0xFF00 == 0x0000
if( ~uc == ucInverted )      // False as it evaluates to: 0xFFFF == 0x00FF
if( uc == ~ucInverted )      // False as it evaluates to: 0x0000 == 0xFF00

Это поведение подтверждается с помощью gcc.

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


person Kenneth    schedule 23.09.2013    source источник
comment
Прочитайте в этом ответе Если ~0 является представлением ловушки , то поведение не определено.   -  person Grijesh Chauhan    schedule 23.09.2013
comment
@GrjeshChauhan: они не подписаны, представление ловушки в этом случае не имеет значения. см. также сноску 53 в 6.2.6.2, связанную со связанным ответом.   -  person Hasturkun    schedule 23.09.2013
comment
@Hasturkun: ~0 не без подписи...   -  person Oliver Charlesworth    schedule 23.09.2013
comment
@OliCharlesworth: Верно. Однако, насколько я понимаю, это все еще не проблема, поскольку есть формулировка, утверждающая, что никакая арифметическая операция над допустимыми значениями не может генерировать представление ловушки, кроме как как часть исключительного условия, такого как переполнение. также для подписанных типов.   -  person Hasturkun    schedule 23.09.2013
comment
Возможный дубликат Путаница с оператором C ~ (побитовое Not) и сравнение переменных char   -  person phuclv    schedule 07.05.2019


Ответы (1)


~uc имеет тип int (значение 0xFFFF). ucInverted имеет тип unsigned char (значение 0xFF), который затем повышается до int (значение 0x00FF). Таким образом, они не равны.

Я думаю, вы могли бы сделать if ((unsigned char)~uc == ucInverted). Оба операнда по-прежнему будут подвергаться повышению, но до повышения они будут иметь одинаковые значения.

person Oliver Charlesworth    schedule 23.09.2013
comment
Мне просто кажется совершенно нелогичным, что вы должны привести unsigned char обратно к unsigned char, чтобы правильно сравнить его с unsigned char. Или это только я? - person Kenneth; 23.09.2013
comment
@Kenneth: Как только кто-то признает, что ~ вызывает продвижение типа, остальное совершенно логично;) - person Oliver Charlesworth; 23.09.2013
comment
~uc скорее всего относится к типу signed int. - person Alexey Frunze; 23.09.2013
comment
Нет, действительно продвижение будет (почти на всех архитектурах) до signed int и никогда до unsigned int. И потом, это тоже не ответ на вопрос. - person Jens Gustedt; 23.09.2013
comment
@JensGustedt: Да, вы правы, целочисленные рекламные акции отдают предпочтение signed везде, где это возможно. Ответ обновлен. (Хотя я не уверен, что вы подразумеваете под не ответом на вопрос?) - person Oliver Charlesworth; 23.09.2013
comment
Я полагаю, что то, что мне это не нравится, не делает это менее верным :) - person Kenneth; 25.09.2013