What is the function to determine the min and max possible of value of datatypes (i.e, int, char.etc) in C?
相关问题
- Multiple sockets for clients to connect to
- What is the best way to do a search in a large fil
- glDrawElements only draws half a quad
- Index of single bit in long integer (in C) [duplic
- Equivalent of std::pair in C
I wrote some macros that return the min and max of any type, regardless of signedness:
Example code:
"But glyph", I hear you asking, "what if I have to determine the maximum value for an opaque type whose maximum might eventually change?" You might continue: "What if it's a typedef in a library I don't control?"
I'm glad you asked, because I just spent a couple of hours cooking up a solution (which I then had to throw away, because it didn't solve my actual problem).
You can use this handy
maxof
macro to determine the size of any valid integer type.You can use it like so:
If you'd like, you can toss a '(t)' onto the front of those macros so they give you a result of the type that you're asking about, and you don't have to do casting to avoid warnings.
Maximum value of any unsigned integral type:
((t)~(t)0)
// Generic expression that would work in almost all circumstances.(~(t)0)
// If you know your typet
have equal or larger size thanunsigned int
. (This cast forces type promotion.)((t)~0U)
// If you know your typet
have smaller size thanunsigned int
. (This cast demotes type after theunsigned int
-type expression~0U
is evaluated.)Maximum value of any signed integral type:
If you have an unsigned variant of type
t
,((t)(((unsigned t)~(unsigned t)0)>>1))
would give you the fastest result you need.Otherwise, use this (thanks to @vinc17 for suggestion):
(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)
Minimum value of any signed integral type:
You have to know the signed number representation of your machine. Most machines use 2's complement, and so
-(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)-1
will work for you.To detect whether your machine uses 2's complement, detect whether
(~(t)0U)
and(t)(-1)
represent the same thing.So, combined with above:
will give you the minimum value of any signed integral type.
As an example: Maximum value of
size_t
(a.k.a. theSIZE_MAX
macro) can be defined as(~(size_t)0)
. Linux kernel source code defineSIZE_MAX
macro this way.One caveat though: All of these expressions use either type casting or
sizeof
operator and so none of these would work in preprocessor conditionals (#if
...#elif
...#endif
and like).(Answer updated for incorpoating suggestions from @chux and @vinc17. Thank you both.)
To get the maximum value of an unsigned integer type
t
whose width is at least the one ofunsigned int
(otherwise one gets problems with integer promotions):~(t) 0
. If one wants to also support shorter types, one can add another cast:(t) ~(t) 0
.If the integer type
t
is signed, assuming that there are no padding bits, one can use:The advantage of this formula is that it is not based on some unsigned version of
t
(or a larger type), which may be unknown or unavailable (evenuintmax_t
may not be sufficient with non-standard extensions). Example with 6 bits (not possible in practice, just for readability):In two's complement, the minimum value is the opposite of the maximum value, minus 1 (in the other integer representations allowed by the ISO C standard, this is just the opposite of the maximum value).
Note: To detect signedness in order to decide which version to use:
(t) -1 < 0
will work with any integer representation, giving 1 (true) for signed integer types and 0 (false) for unsigned integer types. Thus one can use:The header file
limits.h
defines macros that expand to various limits and parameters of the standard integer types.