Заполнение битов в целых числах без знака и побитовые операции в C89

У меня есть много кода, который выполняет побитовые операции с целыми числами без знака. Я написал свой код с предположением, что эти операции выполнялись с целыми числами фиксированной ширины без каких-либо битов заполнения. Например, массив 32-битных целых чисел без знака, из которых все 32 бита доступны для каждого целого числа.

Я хочу сделать свой код более переносимым, и я сосредоточен на том, чтобы быть совместимым с C89 (в данном случае). Одна из проблем, с которыми я столкнулся, - это возможные дополненные целые числа. Возьмем этот крайний пример, взято из руководства GMP :

Однако в векторных системах Cray можно отметить, что short и int всегда хранятся в 8 байтах (и с sizeof , указывающим на это), но используйте только 32 или 46 бит. Это можно объяснить функцией гвоздей, передав, например, 8 * sizeof (int) -INT_BIT .

Я также читал об этом типе заполнения в других местах. Я действительно прочитал сообщение о SO вчера вечером (простите, у меня нет ссылки, и я собираюсь процитировать что-то подобное по памяти), где, если у вас есть, скажем, дубль с 60 используемыми битами, остальные 4 могли бы использоваться для заполнения, и эти биты заполнения могут служить какой-то внутренней цели, поэтому их нельзя изменить.


Скажем, например, мой код скомпилирован на платформе, где тип unsigned int имеет размер 4 байта, каждый из которых составляет 8 бит, однако 2 наиболее значимых бита - это биты заполнения. Будет ли UINT_MAX в этом случае 0x3FFFFFFF (1073741823)?

#include 
#include 

/* padding bits represented by underscores */
int main( int argc, char **argv )
{
    unsigned int a = 0x2AAAAAAA; /* __101010101010101010101010101010 */
    unsigned int b = 0x15555555; /* __010101010101010101010101010101 */
    unsigned int c = a ^ b; /* ?? __111111111111111111111111111111 */
    unsigned int d = c << 5; /* ??  __111111111111111111111111100000 */
    unsigned int e = d >> 5; /* ?? __000001111111111111111111111111 */

    printf( "a: %X\nb: %X\nc: %X\nd: %X\ne: %X\n", a, b, c, d, e );
    return 0;
}
  • Безопасно ли XOR двух целых чисел с битами заполнения?
  • Разве я не могу выполнить XOR независимо от битов заполнения?

Я не могу найти это поведение, описанное в C89.

Кроме того, переменная c гарантированно будет 0x3FFFFFFF , или если, например, два бита заполнения были включены в a или b c будет 0xFFFFFFFF ?

Тот же вопрос с d и e . Могу ли я манипулировать битами заполнения путем сдвига? t I XOR независимо от битов заполнения?

Я не могу найти это поведение, описанное в C89.

Кроме того, переменная c гарантированно будет 0x3FFFFFFF , или если, например, два бита заполнения были включены в a или b c будет 0xFFFFFFFF ?

Тот же вопрос с d и e . Могу ли я манипулировать битами заполнения путем сдвига? t I XOR независимо от битов заполнения?

Я не могу найти это поведение, описанное в C89.

Кроме того, переменная c гарантированно будет 0x3FFFFFFF , или если, например, два бита заполнения были включены в a или b c будет 0xFFFFFFFF ?

Тот же вопрос с d и e . Могу ли я манипулировать битами заполнения путем сдвига? Я ожидал увидеть это ниже, предполагая, что 32 бита с двумя наиболее значимыми битами, используемыми для заполнения, но я хочу знать, гарантировано ли что-то подобное:

a: 2AAAAAAA
b: 15555555
c: 3FFFFFFF
d: 3FFFFFE0
e: 01FFFFFF

Также биты заполнения всегда являются наиболее значимыми битами или могут быть наименее значимые биты?


РЕДАКТИРОВАТЬ 19.12.2010 17:00 EST : Кристоф ответил на мой вопрос. Спасибо!
Я также спросил (выше), всегда ли биты заполнения являются наиболее значимыми битами. Это цитируется в обосновании стандарта C99, и ответ отрицательный. Я перестраховываюсь и предполагаю то же самое и для C89. Вот что конкретно говорится в обосновании C99 для §6.2.6.2 (Представление целочисленных типов):

Биты заполнения доступны пользователю в целочисленных типах без знака. Например, предположим, что машина использует пару 16-битных шорт (каждый со своим собственным битом знака) для создания 32-битного int, а знаковый бит младшего шорт игнорируется при использовании в этом 32-битном int. Затем, как 32-разрядное целое число со знаком, есть бит заполнения (в середине 32-х битов), который игнорируется при определении значения 32-разрядного целого числа со знаком. Но если этот 32-разрядный элемент обрабатывается как 32-разрядное целое число без знака, то этот бит заполнения виден для программы пользователя. Комитету C сказали, что существует машина, которая работает таким образом, и это одна из причин, по которой биты заполнения были добавлены в C99.

В сносках 44 и 45 упоминается, что биты четности могут быть битами заполнения. Комитету неизвестны машины с доступными для пользователя битами четности в пределах целого числа. Поэтому комитету неизвестны машины, которые обрабатывают биты четности как биты заполнения.


РЕДАКТИРОВАТЬ 28.12.2010 3PM EST : Несколько месяцев назад я нашел интересное обсуждение comp.lang.c.

Одно замечание, сделанное Дитмаром, которое мне показалось интересным:

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

17
задан phuclv 1 June 2019 в 11:30
поделиться