Использование sizeof для получения максимальной мощности двух

Есть ли способ в C / C ++ вычислить максимальную степень двух, которая может быть представлена ​​определенным типом данных, используя оператор sizeof?

Например, скажем, у меня есть unsigned short int, Его значения могут варьироваться между 0 а также 65535,
Поэтому максимальная мощность двух, что unsigned short int может содержать 32768,

Я передаю это unsigned short int к функции, и у меня есть (на данный момент) и алгоритм, который выглядит следующим образом:

if (ushortParam > 32768) {
ushortParam = 32768; // Bad hardcoded literals
}

Однако в будущем я, возможно, захочу изменить тип переменной, чтобы включить большие степени двух. Существует ли независимая от типа формула с использованием sizeof (), которая может обеспечить следующее:

if (param > /*Some function...*/sizeof(param) )
{
param = /*Some function...*/sizeof(param);
}

Обратите внимание, что для параметра никогда не потребуется точность с плавающей точкой — только целые числа.

1

Решение

Установка старшего значащего бита вашей переменной для этого размера параметра даст вам наибольшую степень 2.

1 << (8*sizeof(param)-1)
4

Другие решения

Как насчет:

const T max_power_of_two = (std::numeric_limits<T>::max() >> 1) + 1;
3

Чтобы получить максимальную степень 2, представляемую определенным целочисленным типом, вы можете использовать limits.h вместо sizeof оператор. Например:

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

int main() {

int max   = INT_MAX;
int hmax  = max>>1;
int mpow2 = max ^ hmax;

printf("The maximum representable integer is %d\n",max);
printf("The maximum representable power of 2 is %d\n",mpow2);
return 0;
}

Это всегда должно работать, поскольку всегда определяется правильное смещение положительного целого числа. Цитирование из стандартного раздела C 6.5.7.5 (Оператор побитового сдвига):

Результат E1 >> E2 является E1 право смещенной E2 битовые позиции. Если E1
имеет тип без знака или если E1 имеет подписанный тип и неотрицательный
значение, значение результата является неотъемлемой частью отношения
E1 делится на количество, 2 возведенное в степень E2.

Если использование sizeof обязательно вы можете использовать:

1 << (CHAR_BIT*sizeof(param)-1)

для целых типов без знака и:

1 << (CHAR_BIT*sizeof(param)-2)

для целых типов со знаком. Строки выше будут работать только в случае целочисленных типов без битов. Часть стандарта C, обеспечивающая работу этих линий, приведена в разделе 6.2.6.2. Особенно:

Для целых типов без знака, кроме символ без знака, биты
представление объекта должно быть разделено на две группы: биты значения и
биты заполнения (не должно быть ни одного из последних). Если есть N
биты значения, каждый бит должен представлять различную степень 2 между 1
и 2N-1, так что объекты этого типа должны быть способны
представляет значения от 0 до 2N — 1, используя чистый двоичный файл
представление; это должно быть известно как представление значения.

гарантирует первый метод для работы, пока:

Для целочисленных типов со знаком биты представления объекта должны
разделить на три группы: биты значения, биты заполнения и знак
немного. Там не должно быть никаких битов заполнения; должен быть ровно один
знак бит.

Допустимое (не trap) представление объекта целого типа со знаком
где знаковый бит равен нулю, является действительным представлением объекта
соответствующий тип без знака, и должен представлять то же значение.

объясняет, почему во второй строке дан правильный ответ.

2

Принятый ответ, вероятно, будет работать на платформах Posix, но не является общим C / C ++. Предполагается, что CHAR_BIT равен 8, не указывает тип и предполагает, что тип не имеет битов заполнения.

Вот более общие версии для любых / всех целочисленных типов без знака и не требуют включения каких-либо заголовков, зависимостей и т.д .:

#define MAX_VAL(UNSIGNED_TYPE) ((UNSIGNED_TYPE) -1)

#define MAX_POW2(UNSIGNED_TYPE) (~(MAX_VAL(UNSIGNED_TYPE) >> 1))

#define MAX_POW2_VER2(UNSIGNED_TYPE) (MAX_VAL(UNSIGNED_TYPE) ^ (MAX_VAL(UNSIGNED_TYPE) >> 1))

#define MAX_POW2_VER3(UNSIGNED_TYPE) ((MAX_VAL(UNSIGNED_TYPE) >> 1) + 1)

Стандарты, даже C90, гарантируют, что приведение -1 к типу без знака всегда дает максимальное значение, которое может представлять тип. Отсюда все побитовые операторы выше хорошо определены.

http://c0x.coding-guidelines.com/6.3.1.3.html

6.3.1.3 Целые числа со знаком и без знака

682 Когда значение с целочисленным типом преобразуется в другой целочисленный тип, отличный от _Bool, если значение может быть представлено новым типом, оно не изменяется.

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

684 В противном случае новый тип подписывается, и значение не может быть представлено в нем;

685 либо результат определяется реализацией, либо определяется сигнал реализации.

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

http://c0x.coding-guidelines.com/6.2.6.2.html

6.2.6.2 Целочисленные типы

593 Для целых типов без знака, кроме беззнаковых символов, биты представления объекта должны быть разделены на две группы: биты значения и биты заполнения (не должно быть ни одного из последних).

594 Если имеется N битов значения, каждый бит должен представлять различную степень 2 от 1 до 2 ^ (N — 1), так что объекты этого типа должны быть способны представлять значения от 0 до 2 ^ N — 1 с использованием чисто двоичное представление;

595 это должно быть известно как представление значения.

596 Значения любых битов заполнения не указаны.

0
По вопросам рекламы [email protected]