[英]min and max value of data type in C
確定 C 中數據類型(即 int、char.etc)的最小值和最大值的函數是什么?
您需要使用limits.h
,它提供以下常量(根據鏈接的參考):
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
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
PTRDIFF_MIN : minimum value of ptrdiff_t
PTRDIFF_MAX : maximum value of ptrdiff_t
SIZE_MAX : maximum value of size_t
SIG_ATOMIC_MIN : minimum value of sig_atomic_t
SIG_ATOMIC_MAX : maximum value of sig_atomic_t
WINT_MIN : minimum value of wint_t
WINT_MAX : maximum value of wint_t
WCHAR_MIN : minimum value of wchar_t
WCHAR_MAX : maximum value of wchar_t
CHAR_BIT : number of bits in a char
MB_LEN_MAX : maximum length of a multibyte character in bytes
其中U*_MIN
由於顯而易見的原因被省略(任何無符號類型的最小值為 0)。
類似的float.h
為float
和double
類型提供了限制:
FLT_MIN : smallest normalised positive value of a float
FLT_MAX : largest positive finite value of a float
DBL_MIN : smallest normalised positive value of a double
DBL_MAX : largest positive finite value of a double
LDBL_MIN : smallest normalised positive value of a long double
LDBL_MAX : largest positive finite value of a long double
FLT_DIG : the number of decimal digits guaranteed to be preserved converting from text to float and back to text
DBL_DIG : the number of decimal digits guaranteed to be preserved converting from text to double and back to text
LDBL_DIG : the number of decimal digits guaranteed to be preserved converting from text to long double and back to text
浮點類型圍繞零對稱,因此最負的有限數是最正的有限數的否定 - 例如float
范圍從-FLT_MAX
到FLT_MAX
。
請注意,浮點類型只能准確表示其范圍內的少量有限數量的值。 隨着存儲的絕對值變大,可以精確表示的相鄰數字之間的間距也變大。
“但是字形”,我聽到你問,“如果我必須確定一個不透明類型的最大值,它的最大值最終可能會改變呢?” 您可能會繼續:“如果它是我無法控制的庫中的 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)',這樣它們就會為您提供您所詢問的類型的結果,並且您不必進行強制轉換以避免警告。
任何無符號整數類型的最大值:
((t)~(t)0)
// 幾乎適用於所有情況的通用表達式。
(~(t)0)
// 如果你知道你的類型t
大小等於或大於unsigned int
。 (此施法力型晉升。)
((t)~0U)
// 如果你知道你的類型t
大小小於unsigned int
。 (在評估unsigned int
類型表達式~0U
之后,此~0U
將類型~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
宏。
但需要注意的是:所有這些表達式都使用類型轉換或sizeof
運算符,因此這些表達式都不適用於預處理器條件( #if
... #elif
... #endif
等)。
(已更新答案以納入來自 @chux 和 @vinc17 的建議。謝謝你們。)
頭文件limits.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)
示例代碼:
#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;
}
#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;
}
要獲得寬度至少為unsigned int
之一的unsigned int
符號整數類型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
可以在不使用任何庫函數的情況下計算任何整數數據類型的 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));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.