По SuSv3, ssize_t
должен быть целочисленным типом со знаком. Если я хочу проверить, больше ли вычисляемое мной значение, чем максимально допустимое значение для такого типа данных, я могу сравнить его с INT_MAX
что не приятно.
Есть ли более переносимый способ, которым это сравнение может быть сделано — макрос / функция f
это работает как в
f(<typedef'ed datatype>) = {maximum value allowed for <TDDT> on this system)?
, или короткая последовательность таких операций того же рода?
система:
Ubuntu 12.04.
glibc 2.15
Ядро 3.2.0
P.S .: При поиске в Google, я сначала подумал, что расширение gcc ‘typeof’ звучит многообещающе; но это, казалось, не помогло здесь (или делает это?). Это значит, что я в порядке со всем, что может быть расширением / атрибутом gcc / и т.д.
Для беззнакового арифметического типа (type)-1
это максимальное значение. Поскольку вы не знаете, каков относительный размер типов, приведите к uintmax_t
:
#define UNSIGNED_TYPE_MAX(t) ((uintmax_t)(t)-1)
if ((uintmax_t)x > UNSIGNED_TYPE_MAX(size_t)) puts("too large");
Для подписанных типов такого ярлыка нет. На самом деле, я не думаю, что есть какой-либо способ определения наибольшего значения типа со знаком в строго переносимом C89 или C99, без использования соответствующей константы, такой как SSIZE_MAX
за ssize_t
, C99 определяет константы для каждого типа, предназначенного для арифметики, определенной в stdint.h
для типов, определенных в ISO C. Для типов, определенных в POSIX, но не в стандартном C, существует много значений в limits.h
; обратите внимание, что они являются пределом допустимых значений для того, для чего предназначен тип, а не пределом того, что может вписываться в тип. Например, если size_t
это 32-битный тип, то SIZE_MAX
гарантированно будет 232-1, тогда как SSIZE_MAX
может быть меньше 231-1, если реализация не поддерживает число байтов больше этого.
С дополнительным предположением, что целые числа представлены в двоичном коде и нет битов заполнения, что безопасно, если вы ограничиваете себя POSIX (где CHAR_BIT
является всегда 8), вы можете определить максимальное значение, рассчитав размер типа: в знаковом типе есть один знаковый бит, а все остальное — бит значения.
#define SIGNED_TYPE_MAX(t) (((uintmax_t)1 << (sizeof(t) * CHAR_BIT - 1)) - 1)
Обратите внимание, что такие вещи, как «удвоение, пока оно не перестанет расти» или «пуш в битовой комбинации 0111… 111» являются хитрыми. Стандарт C говорит, что поведение для типов со знаком не определено, и GCC использует это для оптимизации операций над типами со знаком, что может привести к неверному значению в случае переполнения. Например, он может выполнять вычисления в регистре большего размера, так что переполнение оказывается невозможным.
Других решений пока нет …