Что такое CHAR_BIT? - PullRequest
       6

Что такое CHAR_BIT?

83 голосов
/ 08 июля 2010

Цитирование кода для вычисления целочисленного абсолютного значения (абс) без ветвления из http://graphics.stanford.edu/~seander/bithacks.html:

int v;           // we want to find the absolute value of v
unsigned int r;  // the result goes here 
int const mask = v >> sizeof(int) * CHAR_BIT - 1;

r = (v + mask) ^ mask;

Запатентованный вариант:

r = (v ^ mask) - mask;

Что такое CHAR_BIT и как его использоватьэто?

Ответы [ 3 ]

200 голосов
/ 08 июля 2010

CHAR_BIT - количество бит в char. В наши дни почти все архитектуры используют 8 бит на байт, но это не всегда так. Некоторые старые машины имели 7-битный байт.

Можно найти в <limits.h>.

2 голосов
/ 03 октября 2017

Попытка ответить и на явный вопрос (что такое CHAR_BIT), и на неявный вопрос (как это работает) в исходном вопросе.


Символ в C и C ++ представляет наименьшую единицупамять, которую программа C может адресовать *

CHAR_BIT в C, а C ++ представляет количество бит в символе.Это должно быть как минимум 8 из-за других требований к типу char.На практике на всех современных компьютерах общего назначения это ровно 8, но некоторые исторические или специализированные системы могут иметь более высокие значения.

Java не имеет эквивалента CHAR_BIT или sizeof, в этом нет необходимости, так как все примитивные типы в Javaимеют фиксированный размер, а внутренняя структура объектов непрозрачна для программиста.При переводе этого кода на Java вы можете просто заменить «sizeof (int) * CHAR_BIT - 1» на фиксированное значение 31.

В этом конкретном коде он используется для вычисления количества бит в int.Помните, что в этом вычислении предполагается, что тип int не содержит битов заполнения.

Предполагая, что ваш компилятор выбирает расширение знака при сдвигах битов чисел со знаком, и предполагая, что ваша система использует представление дополнения 2s для отрицательных чисел, этоозначает, что «MASK» будет 0 для положительного или нулевого значения и -1 для отрицательного значения.

Чтобы отменить число дополнения до двух, нам нужно выполнить побитовое значение не, а затем добавить единицу.Эквивалентно мы можем вычесть единицу, а затем поразрядно отрицать ее.

Снова предполагая, что представление дополнения до двух представляется всеми единицами, поэтому исключающее или с -1 эквивалентно побитовому отрицанию.v равно нулю, число оставлено в покое, когда v равно единице, оно отрицается.

Следует иметь в виду, что переполнение со знаком в C и C ++ является неопределенным поведением.Таким образом, использование этой реализации ABS для наиболее отрицательного значения приводит к неопределенному поведению.Это можно исправить путем добавления приведений так, чтобы последняя строка программы оценивалась в unsigned int.

*, которая обычно, но не всегда, совпадает с наименьшей единицей памяти, которую может адресовать аппаратное обеспечение.Реализация может потенциально объединить несколько единиц памяти с аппаратной адресацией в одну единицу памяти с программной адресацией или разделить одну единицу памяти с аппаратной адресацией на несколько единиц памяти с программной адресацией.

2 голосов
/ 08 июля 2010

Вы должны знать, что этот код зависит от определяемого реализацией поведения правильного сдвига битов для подписанных типов. gcc обещает всегда давать вменяемое поведение (расширение знака-бита), но ISO C позволяет реализации заполнять нулями старшие биты.

Один из способов решения этой проблемы:

#ifdef HAVE_SIGN_EXTENDING_BITSHIFT
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
#else
int const mask = -((unsigned)v >> sizeof(int) * CHAR_BIT - 1);
#endif

Ваш Makefile или config.h и т. Д. Может определять HAVE_SIGN_EXTENDING_BITSHIFT во время сборки в зависимости от вашей платформы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...