Мне немного любопытно создать макрос для генерации битовой маски для регистра устройства, до 64 бит. Так, что BIT_MASK(31)
производит 0xffffffff
.
Тем не менее, несколько примеров C не работают, как я думал, вместо этого я получаю 0x7fffffff
. Это как если компилятор предполагает, что я хочу подписанный вывод, а не беззнаковый. Итак, я попытался 32
и заметил, что значение возвращается к 0. Это связано со стандартами C, утверждающими, что если значение сдвига больше или равно количеству битов в операнде, подлежащем сдвигу, то результат не определено Это имеет смысл.
Но, учитывая следующую программу, bits2.c
:
#include <stdio.h>
#define BIT_MASK(foo) ((unsigned int)(1 << foo) - 1)
int main()
{
unsigned int foo;
char *s = "32";
foo = atoi(s);
printf("%d %.8x\n", foo, BIT_MASK(foo));
foo = 32;
printf("%d %.8x\n", foo, BIT_MASK(foo));
return (0);
}
Если я скомпилирую с gcc -O2 bits2.c -o bits2
и запусту его на компьютере с Linux / x86_64, я получу следующее:
32 00000000
32 ffffffff
Если я возьму тот же код и скомпилирую его на компьютере с Linux / MIPS (big-endian), я получу следующее:
32 00000000
32 00000000
На компьютере x86_64, если я использую gcc -O0 bits2.c -o bits2
, я получаю:
32 00000000
32 00000000
Если я настрою BIT_MASK
на ((unsigned int)(1UL << foo) - 1)
, то результат будет 32 00000000
для обеих форм, независимо от уровня оптимизации gcc.
Похоже, что в x86_64 gcc оптимизирует что-то неправильно ИЛИ неопределенная природа сдвига влево 32-битного 32-битного числа определяется аппаратным обеспечением каждой платформы.
Учитывая все вышесказанное, возможно ли программно создать макрос C, который создает битовую маску из одного бита или диапазона битов?
т.е:.
BIT_MASK(6) = 0x40
BIT_FIELD_MASK(8, 12) = 0x1f00
Предположим, что BIT_MASK
и BIT_FIELD_MASK
работают с 0-индекса (0-31). BIT_FIELD_MASK
- создать маску из битового диапазона, то есть 8:12
.