У меня есть много кода, который выполняет побитовые операции с целыми числами без знака. Я написал свой код с предположением, что эти операции выполнялись с целыми числами фиксированной ширины без каких-либо битов заполнения. Например, массив 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;
}
Я не могу найти это поведение, описанное в 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.
Одно замечание, сделанное Дитмаром, которое мне показалось интересным:
Отметим, что биты заполнения не являются необходимыми для существования представлений ловушек; также подойдут комбинации битов значений, которые не представляют значение типа объекта.