минимальное и максимальное значение типа данных в C - PullRequest
71 голосов
/ 13 января 2010

Какова функция для определения минимального и максимального возможного значения типов данных (т.е. int, char.etc) в C?

Ответы [ 9 ]

87 голосов
/ 13 января 2010

Вы захотите использовать limits.h, который обеспечивает следующие константы (согласно связанной ссылке):

CHAR_BIT   = number of bits in a char
SCHAR_MIN  = minimum value for a signed char
SCHAR_MAX  = maximum value for a signed char
UCHAR_MAX  = maximum value for an unsigned char
CHAR_MIN   = minimum value for a char
CHAR_MAX   = maximum value for a char
MB_LEN_MAX = maximum multibyte length of a character accross locales
SHRT_MIN   = minimum value for a short
SHRT_MAX   = maximum value for a short
USHRT_MAX  = maximum value for an unsigned short
INT_MIN    = minimum value for an int
INT_MAX    = maximum value for an int
UINT_MAX   = maximum value for an unsigned int
LONG_MIN   = minimum value for a long
LONG_MAX   = maximum value for a long
ULONG_MAX  = maximum value for an unsigned long
LLONG_MIN  = minimum value for a long long
LLONG_MAX  = maximum value for a long long
ULLONG_MAX = maximum value for an unsigned long long

Где U*_MIN опущено по понятным причинам (любой тип без знака имеет минимальное значение 0).

Аналогично float.h предоставляет ограничения для типов float и double:

-FLT_MAX = most negative value of a float
FLT_MAX  = max value of a float
-DBL_MAX = most negative value of a double
DBL_MAX  = max value of a double
-LDBL_MAX = most negative value of a long double
LDBL_MAX = max value of a long double

Вы должны внимательно прочитать статью на floats.h, хотя float и double могут содержать предписанные минимальные и максимальные значения, но точность, с которой каждый тип может представлять данные, может не соответствовать тому, что вы пытаетесь хранить. В частности, трудно хранить исключительно большие числа с очень малыми фракциями. Так что float.h предоставляет ряд других констант, которые помогут вам определить, может ли float или double на самом деле представлять конкретное число.

26 голосов
/ 01 сентября 2011

"Но глиф", я слышу, вы спрашиваете: "Что если мне нужно определить максимальное значение для непрозрачного типа, чей максимум может в конечном итоге измениться?" Вы можете продолжить: «Что если это typedef в библиотеке, которой я не управляю?»

Я рад, что вы спросили, потому что я просто потратил пару часов на приготовление решения (которое мне потом пришлось выбросить, потому что оно не решило мою настоящую проблему).

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

#define issigned(t) (((t)(-1)) < ((t) 0))

#define umaxof(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | \
                    (0xFULL << ((sizeof(t) * 8ULL) - 4ULL)))

#define smaxof(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | \
                    (0x7ULL << ((sizeof(t) * 8ULL) - 4ULL)))

#define maxof(t) ((unsigned long long) (issigned(t) ? smaxof(t) : umaxof(t)))

Вы можете использовать его так:

int main(int argc, char** argv) {
    printf("schar: %llx uchar: %llx\n", maxof(char), maxof(unsigned char));
    printf("sshort: %llx ushort: %llx\n", maxof(short), maxof(unsigned short));
    printf("sint: %llx uint: %llx\n", maxof(int), maxof(unsigned int));
    printf("slong: %llx ulong: %llx\n", maxof(long), maxof(unsigned long));
    printf("slong long: %llx ulong long: %llx\n",
           maxof(long long), maxof(unsigned long long));
    return 0;
}

Если вы хотите, вы можете добавить '(t)' в начало этих макросов, чтобы они дали вам результат того типа, о котором вы спрашиваете, и вам не нужно выполнять приведение к избегать предупреждений.

5 голосов
/ 15 сентября 2016

Максимальное значение любого без знака целочисленный тип:

  • ((t)~(t)0) // Общее выражение, которое будет работать почти во всех обстоятельства.

  • (~(t)0) // Если вы знаете, что ваш тип t имеет такой же или больший размер, чем unsigned int. (Это приведение типов к действию).

  • ((t)~0U) // Если вы знаете, что ваш тип t имеет меньший размер, чем unsigned int. (Это приведение понижает тип после unsigned int -типа выражение ~0U оценивается.)

Максимальное значение любого со знаком целочисленного типа:

  • Если у вас есть вариант без знака типа t, ((t)(((unsigned t)~(unsigned t)0)>>1)) даст вам самый быстрый результат, который вам нужен.

  • В противном случае используйте это (спасибо @ vinc17 за предложение): (((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)

Минимальное значение любого со знаком целочисленного типа:

Вы должны знать числовое представление вашей машины. Большинство машин используют 2 дополнения, и поэтому -(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)-1 будет работать для вас.

Чтобы определить, использует ли ваша машина 2 дополнения, определите, представляют ли (~(t)0U) и (t)(-1) одно и то же.

Итак, в сочетании с вышеприведенным:

(-(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)-(((~(t)0U)==(t)(-1)))

даст вам минимальное значение для любого целочисленного типа со знаком.

В качестве примера: максимальное значение size_t (например, макрос SIZE_MAX) можно определить как (~(size_t)0). Исходный код ядра Linux определить макрос SIZE_MAX таким образом.

One caveat : все эти выражения используют приведение типов или оператор sizeof, поэтому ни одно из них не будет работать в условных выражениях препроцессора (#if ... #elif ... #endif и т.п.).

(Ответ обновлен за включение предложений от @chux и @ vinc17. Спасибо вам обоим.)

4 голосов
/ 21 марта 2017
#include<stdio.h>

int main(void)
{
    printf("Minimum Signed Char %d\n",-(char)((unsigned char) ~0 >> 1) - 1);
    printf("Maximum Signed Char %d\n",(char) ((unsigned char) ~0 >> 1));

    printf("Minimum Signed Short %d\n",-(short)((unsigned short)~0 >>1) -1);
    printf("Maximum Signed Short %d\n",(short)((unsigned short)~0 >> 1));

    printf("Minimum Signed Int %d\n",-(int)((unsigned int)~0 >> 1) -1);
    printf("Maximum Signed Int %d\n",(int)((unsigned int)~0 >> 1));

    printf("Minimum Signed Long %ld\n",-(long)((unsigned long)~0 >>1) -1);
    printf("Maximum signed Long %ld\n",(long)((unsigned long)~0 >> 1));

    /* Unsigned Maximum Values */

    printf("Maximum Unsigned Char %d\n",(unsigned char)~0);
    printf("Maximum Unsigned Short %d\n",(unsigned short)~0);
    printf("Maximum Unsigned Int %u\n",(unsigned int)~0);
    printf("Maximum Unsigned Long %lu\n",(unsigned long)~0);

    return 0;
}
3 голосов
/ 05 февраля 2015

Я написал несколько макросов, которые возвращают минимальное и максимальное значения любого типа независимо от подписи:

#define MAX_OF(type) \
    (((type)(~0LLU) > (type)((1LLU<<((sizeof(type)<<3)-1))-1LLU)) ? (long long unsigned int)(type)(~0LLU) : (long long unsigned int)(type)((1LLU<<((sizeof(type)<<3)-1))-1LLU))
#define MIN_OF(type) \
    (((type)(1LLU<<((sizeof(type)<<3)-1)) < (type)1) ? (long long int)((~0LLU)-((1LLU<<((sizeof(type)<<3)-1))-1LLU)) : 0LL)

Пример кода:

#include <stdio.h>
#include <sys/types.h>
#include <inttypes.h>

#define MAX_OF(type) \
    (((type)(~0LLU) > (type)((1LLU<<((sizeof(type)<<3)-1))-1LLU)) ? (long long unsigned int)(type)(~0LLU) : (long long unsigned int)(type)((1LLU<<((sizeof(type)<<3)-1))-1LLU))
#define MIN_OF(type) \
    (((type)(1LLU<<((sizeof(type)<<3)-1)) < (type)1) ? (long long int)((~0LLU)-((1LLU<<((sizeof(type)<<3)-1))-1LLU)) : 0LL)

int main(void)
{
    printf("uint32_t = %lld..%llu\n", MIN_OF(uint32_t), MAX_OF(uint32_t));
    printf("int32_t = %lld..%llu\n", MIN_OF(int32_t), MAX_OF(int32_t));
    printf("uint64_t = %lld..%llu\n", MIN_OF(uint64_t), MAX_OF(uint64_t));
    printf("int64_t = %lld..%llu\n", MIN_OF(int64_t), MAX_OF(int64_t));
    printf("size_t = %lld..%llu\n", MIN_OF(size_t), MAX_OF(size_t));
    printf("ssize_t = %lld..%llu\n", MIN_OF(ssize_t), MAX_OF(ssize_t));
    printf("pid_t = %lld..%llu\n", MIN_OF(pid_t), MAX_OF(pid_t));
    printf("time_t = %lld..%llu\n", MIN_OF(time_t), MAX_OF(time_t));
    printf("intptr_t = %lld..%llu\n", MIN_OF(intptr_t), MAX_OF(intptr_t));
    printf("unsigned char = %lld..%llu\n", MIN_OF(unsigned char), MAX_OF(unsigned char));
    printf("char = %lld..%llu\n", MIN_OF(char), MAX_OF(char));
    printf("uint8_t = %lld..%llu\n", MIN_OF(uint8_t), MAX_OF(uint8_t));
    printf("int8_t = %lld..%llu\n", MIN_OF(int8_t), MAX_OF(int8_t));
    printf("uint16_t = %lld..%llu\n", MIN_OF(uint16_t), MAX_OF(uint16_t));
    printf("int16_t = %lld..%llu\n", MIN_OF(int16_t), MAX_OF(int16_t));
    printf("int = %lld..%llu\n", MIN_OF(int), MAX_OF(int));
    printf("long int = %lld..%llu\n", MIN_OF(long int), MAX_OF(long int));
    printf("long long int = %lld..%llu\n", MIN_OF(long long int), MAX_OF(long long int));
    printf("off_t = %lld..%llu\n", MIN_OF(off_t), MAX_OF(off_t));

    return 0;
}
3 голосов
/ 13 января 2010

Просмотрите эти страницы в limit.h и float.h , которые включены в стандартную библиотеку c.

3 голосов
/ 13 января 2010

Заголовочный файл limits.h определяет макросы, которые расширяются до различных пределов и параметров стандартных целочисленных типов.

2 голосов
/ 05 октября 2016

Чтобы получить максимальное значение целочисленного типа без знака t, ширина которого по крайней мере равна ширине unsigned int (в противном случае возникают проблемы с целочисленными повышениями): ~(t) 0. Если кто-то также хочет поддерживать более короткие типы, он может добавить другое приведение: (t) ~(t) 0.

Если целочисленный тип t подписан, при условии, что нет битов заполнения, можно использовать:

((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1)

Преимущество этой формулы в том, что она не основана на какой-либо неподписанной версии t (или более крупного типа), которая может быть неизвестна или недоступна (даже uintmax_t может быть недостаточно для нестандартных расширений) , Пример с 6 битами (на практике это невозможно, просто для удобства чтения):

010000  (t) 1 << (sizeof(t) * CHAR_BIT - 2)
001111  - 1
011110  * 2
011111  + 1

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

Примечание: Чтобы определить подпись, чтобы решить, какую версию использовать: (t) -1 < 0 будет работать с любым целочисленным представлением, давая 1 (true) для целых типов со знаком и 0 (false) для целых типов без знака. Таким образом можно использовать:

(t) -1 < 0 ? ((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1) : (t) ~(t) 0
0 голосов
/ 27 июля 2016

MIN и MAX значения любого целочисленного типа данных могут быть вычислены без использования каких-либо библиотечных функций, как показано ниже, и та же логика может применяться к другим целочисленным типам short, int и long.

printf("Signed Char : MIN -> %d & Max -> %d\n", ~(char)((unsigned char)~0>>1), (char)((unsigned char)~0 >> 1));
printf("Unsigned Char : MIN -> %u & Max -> %u\n", (unsigned char)0, (unsigned char)(~0));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...