Иногда я сталкиваюсь с целым типом (например, целочисленным типом подписи POSIX off_t
), где было бы полезно иметь макрос для его минимальных и максимальных значений, но я не знаю, как создать тот, который действительно портативный.
Для неподписанных целых типов я всегда думал, что это просто. 0
для минимума и ~0
для максимума. С тех пор я прочитал несколько разных потоков SO, которые предлагают использовать -1
вместо ~0
для переносимости. Интересная тема с некоторыми утверждениями здесь:
С++ - Можно ли использовать -1 для установки всех битов в true? - Переполнение стека
Однако даже после прочтения этой проблемы я все еще запутался. Кроме того, я ищу что-то совместимое с C89 и C99, поэтому я не знаю, применяются ли те же методы. Скажем, у меня был тип uint_whatever_t
. Не могу ли я просто передать 0, а затем побитовое дополнение? Это будет нормально?:
#define UINT_WHATEVER_T_MAX ( ~ (uint_whatever_t) 0 )
Подписанные целые типы выглядят так, будто они будут более жесткими, чтобы треснуть. Я видел несколько различных возможных решений, но только один представляется переносимым. Либо это, либо неверно. Я нашел его во время игры в google для OFF_T_MAX и OFF_T_MIN. Кредит Кристиану Биере:
#define MAX_INT_VAL_STEP(t) \
((t) 1 << (CHAR_BIT * sizeof(t) - 1 - ((t) -1 < 1)))
#define MAX_INT_VAL(t) \
((MAX_INT_VAL_STEP(t) - 1) + MAX_INT_VAL_STEP(t))
#define MIN_INT_VAL(t) \
((t) -MAX_INT_VAL(t) - 1)
[...]
#define OFF_T_MAX MAX_INT_VAL(off_t)
Я не мог найти ничего относительно различных допустимых типов знаковых целочисленных представлений в C89, но C99 имеет примечания для целых переносимости в §J.5.5:
Представлены ли целые числа со знаком с использованием знака и величины, дополнения или дополнения, и является ли экстраординарное значение ловушкой представление или обычное значение (6.2.6.2).
Это, по-видимому, подразумевает, что могут использоваться только те три перечисленные подписанные числа. Является ли импликация правильной, и макросы выше совместимы со всеми тремя представлениями?
Другие мысли:
Кажется, что функционально подобный макрос
MAX_INT_VAL_STEP()
дал бы неправильный результат, если бы были биты заполнения. Интересно, есть ли что-то в этом роде.
Чтение через подписанных числовых представлений в Википедии мне приходит в голову, что для всех трех подписанных целочисленных представлений любой знаковый целочисленный тип MAX будет: < ш > знак бит выключен, все биты значений на (все три)
И его MIN будет либо:
бит знака включен, все биты значения на (знак и величина)
бит знака включен, все биты значения выключены (единицы/два дополнения)
Я думаю, что могу проверить знак и величину, сделав это:
#define OFF_T_MIN ( ( ( (off_t)1 | ( ~ (off_t) -1 ) ) != (off_t)1 ) ? /* sign and magnitude minimum value here */ : /* ones and twos complement minimum value here */ )
Тогда, когда знак и величина являются битами знака, а все биты значений не будут минимальными для off_t в этом случае be ~ (off_t) 0
? И для одного/двухкратного минимума мне понадобится какой-то способ отключить все биты значений, но оставить бит знака включенным. Не знаю, как это сделать, не зная количества битов значения. Кроме того, знак бит гарантированно всегда будет более значительным, чем бит наиболее значимого значения?
Спасибо, и, пожалуйста, дайте мне знать, если это слишком длинное сообщение
РЕДАКТИРОВАТЬ 12/29/2010 5PM EST:
Как было сказано ниже, чтобы получить максимальное значение unsigned type, (unsigned type)-1
более корректно, чем ~0
или даже ~(unsigned type)0
. Из того, что я могу собрать, когда вы используете -1, это то же самое, что и 0-1, что всегда приведет к максимальному значению в неподписанном типе.
Кроме того, поскольку максимальное значение неподписанного типа может быть определено, можно определить, сколько бит значения находится в неподписанном типе. Поблагодарите Hallvard B. Furuseth за его функциональный макрос IMAX_BITS(), который он опубликовал в ответ на вопрос на comp.lang.c
/* Number of bits in inttype_MAX, or in any (1<<b)-1 where 0 <= b < 3E+10 */
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 \
+ (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%31+3))
IMAX_BITS (INT_MAX) вычисляет количество бит в int, а IMAX_BITS ((unsigned_type) -1) вычисляет количество бит в unsigned_type. Пока кто-то не реализует 4-гигабайтные целые числа, в любом случае: -)
Сердце моего вопроса, однако, остается без ответа: как определить минимальное и максимальное значения подписанного типа с помощью макроса. Я все еще смотрю на это. Может быть, ответ - нет ответа.
Если вы не просматриваете этот вопрос в StackOverflow, в большинстве случаев вы не можете видеть предлагаемые ответы до тех пор, пока они не будут приняты. Предлагается qaru.site/info/9929/....