Установить самый старший бит в C
Я пытаюсь установить самый старший бит в long long unsigned, x.
Для этого я использую эту строку кода:
x |= 1<<((sizeof(x)*8)-1);
Я думал, что это должно работать, потому что sizeof задает размер в байтах, поэтому я умножился на 8 и вычитал один, чтобы установить последний бит. Всякий раз, когда я это делаю, компилятор имеет это предупреждение: "предупреждение: количество сдвигов влево >= ширина типа"
Я не понимаю, почему эта ошибка возникает.
Ответы
Ответ 1
Перемещаемый 1
- это константа типа int
, что означает, что вы смещаете значение int
на биты sizeof(unsigned long long) * 8) - 1
. Этот сдвиг может быть легко больше, чем ширина int
, что, по-видимому, произошло в вашем случае.
Если вы хотите получить некоторую маску маски-маски типа unsigned long long
, вы должны начать с начальной битовой маски типа unsigned long long
, а не типа int
.
1ull << (sizeof(x) * CHAR_BIT) - 1
Возможно, лучший способ создать ту же маску -
~(-1ull >> 1)
или
~(~0ull >> 1)
Ответ 2
используют 1ULL < вместо 1 <
Используя только "1", вы перемещаете целое число. 1ULL будет беззнаковым длинным, что вам нужно.
Целое число будет, вероятно, 32 бита и long long
, вероятно, 64 бита в ширину. Итак, смещение:
1 << ((sizeof(long long)*8)-1)
будет (скорее всего):
1 << 63
Так как 1 - это целое число, которое (скорее всего) 32 бита, вы получаете предупреждение, потому что вы пытаетесь перейти от MSB 32-битного значения.
Ответ 3
Литерал 1
, который вы меняете, не является автоматически unsigned long long
(но int
) и, следовательно, не имеет столько бит, сколько вам нужно. Закрепите его с помощью ULL
(т.е. 1ULL
) или переведите его на unsigned long long
перед тем, как сдвинуть его, чтобы сделать его правильным.
Кроме того, чтобы быть более безопасным для странных платформ, замените 8
на CHAR_BIT
. Обратите внимание, что это по-прежнему не всегда лучший способ установить самый старший бит, см., Например, этот вопрос для альтернатив.
Вы также должны рассмотреть возможность использования такого типа, как uint64_t
, если вы предполагаете unsigned long long
быть определенной шириной или uint_fast64_t
/uint_least64_t
, если вам нужна хотя бы определенная ширина, или uintmax_t
если вам нужен самый большой доступный тип.
Ответ 4
Благодаря 2-символьному представлению отрицательных целых чисел наиболее отрицательным интергером является именно желаемая битовая диаграмма только с набором MSB. Поэтому x |= (unsigned long long )LONG_LONG_MIN;
тоже должен работать.