2010-01-13 23 views

ответ

78

Вы хотите использовать 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 могут представлять конкретное число.

+1

Какое значение минимальное и максимальное значение поплавка? – SuperString

+0

FLT_MAX и FLT_MIN –

+2

'SIZE_MAX' (максимальный размер' size_t') является еще одним полезным. – caf

3

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

+0

Каково минимальное значение unsigned char? – SuperString

+4

@Superstring, минимальное значение любого * неподписанного * типа равно 0. –

+4

Я хочу отрицательные значения без знака! :-) –

3

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

23

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

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

Вы можете использовать этот удобный макрос 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; 
} 

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

+0

Не будет '~ ((t) 0)' работать для max без знака? (это не так, но я пока не знаю, почему). – Gauthier

+0

Ну, это действительно работает, но требует описанного вами типа. – Gauthier

+0

[Как определить, если тип подписан] (http://stackoverflow.com/a/7470062/991816) – DanSkeel

3

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

#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; 
} 
0

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)); 
4

Максимальное значение любого знака интегрального типа: (~(t)0)

Максимальное значение любого подписанного интегрального типа: Если у вас есть неподписанный вариант типа т, ((t)((~(unsigned t)0)>>1)) даст вам самый быстрый результат, который вам нужен (см. пример в исходном коде ядра Linux, приведенном ниже). В противном случае вы, вероятно, должны использовать (~(1ULL<<(sizeof(t)*CHAR_BIT-1))).

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

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

((~(t)0U) == (t)(-1) ? -(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))-1 : 
         -(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))) 

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

Например: (~ (size_t) 0) дает максимальное значение size_t. (И угадайте, что это как SIZE_MAX это с помощью #define в Linux kernel source code.)

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

0

Чтобы получить максимальное значение целого числа без знака t, ширина которого не меньше unsigned int (в противном случае возникают проблемы с целыми рекламными акциями): ~(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 стандарт, это как раз противоположно максимальному значению).

3
#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; 
} 
+0

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

+0

Это отличный, независимый от системы ответ, который демонстрирует понимание типов, памяти и, конечно, побитовых операторов С. –

Смежные вопросы