В стандарте языка указано, что для для представления целочисленных типов (integral types) допускается использовать один из трёх способов:
В связи с чем возникает несколько вопросов:
В настоящее время где-нибудь вообще используется представление целых чисел, отличное от 2's complement?
Допускает ли стандарт, чтобы в рамках одной и той же реализации использовались различные представления для целочисленных типов? Например, чтобы char
был 2's complement, а int
был 1's complement?
Как различные представления целых согласуются с битовыми операциями? Например, пусть есть такой код:
unsigned char a = 1;
a = ~a;
И пусть в некоторой реализации используется восьмибитный char
и шестнадцатибитный int
, и для представления целых знаковых чисел применяется 1's complement, т.е. отрицательные значения мы храним в обратном коде. У меня сложилось впечатление, что для вычисления значения переменной a
могут быть проделаны следующие преобразования:
a
подвергнется целочисленному расширению до int
, ибо операнд битового отрицания, согласно стандарту, может быть расширен. Т.е. набор битов 00000001
преобразуется в 00000000 00000001
.11111111 11111110
.-1
.-1
будет приведено к беззнаковому целому unsigned char
по модулю 256
. Т.е. переменная a
примет значение 255
, которое кодируется следующей последовательностью бит: 11111111
. Что несколько странно, ибо используя битовое отрицание к последовательности бит 00000001
, я ожидаю получить 11111110
, а не 11111111
. Допускается ли стандартом такая работа битового отрицания, или приведённый выше пример в корне не верен?
Говорят, что системы типа UNISYS 2200 (1, 2) еще встречаются кое-где в реальной жизни. Штатный компилятор С в этих системах использует 1's-complement представление.
См. также
Are there any non-twos-complement implementations of C?
Exotic architectures the standards committees care about
Прямого запрета на смешение представлений в стандарте нет. Да и нет в таком запрете никакого смысла, ибо никакой пользы он бы не принес - стандарт и так не гарантирует вам никакой "синхронизированности" между представлениями разных знаковых целых типов. Например, каждый целый тип может обладать своим количеством и расположением padding-битов.
Ваша интерпретация работы оператора ~
совершенно верна. Да, такое поведение допускается. Да, поведение "малых" беззнаковых типов в таких контекстах существенно зависит от выбранного представления знаковых типов. Точнее, побитовое поведение знаковых типов очевидным образом зависит от выбранного представления, а "малые" беззнаковые типы уже становятся заложниками этого поведения через посредство integral promotions.
Можно также отметить, что применение ~
к знаковому значению может породить и trap representation.
(Свою роль тут также сыграл сделанный на этапе формирования C89/90 выбор в пользу выполнения расширения беззнаковых типов к знаковому int
, как описано в Rationale к стандарту (см. вторую часть моего ответа здесь), вопреки имевшей место тогда юниксовой традиции расширения беззнаковых типов к unsigned int
.)
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Пробовал несколько найденных в сети инструкций - результат всегда одинаковый:
Что не так с реализацией, почему пишет "множественное определение" всех методов за классом? Пишу в QtCreator
Есть функция, принимающая rvalue ссылку и передающая её другой функции, принимающей rvalue ссылку:
Есть проект, в нем обрабатывает внешняя библиотека, у которой есть функции обратного вызоваКогда происходит событие функция обратного вызова...