min and max value of data type in C

后端 未结 9 1612
借酒劲吻你
借酒劲吻你 2020-11-29 17:51

What is the function to determine the min and max possible of value of datatypes (i.e, int, char.etc) in C?

相关标签:
9条回答
  • 2020-11-29 18:27

    To get the maximum value of an unsigned integer type t whose width is at least the one of unsigned 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:

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

    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 (even uintmax_t may not be sufficient with non-standard extensions). Example with 6 bits (not possible in practice, just for readability):

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

    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:

    (t) -1 < 0 ? ((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1) : (t) ~(t) 0
    
    0 讨论(0)
  • 2020-11-29 18:34

    "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.

    #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)))
    

    You can use it like so:

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

    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.

    0 讨论(0)
  • 2020-11-29 18:34
    #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)
  • 2020-11-29 18:40

    I wrote some macros that return the min and max of any type, regardless of signedness:

    #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)
    

    Example code:

    #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 讨论(0)
  • 2020-11-29 18:40

    MIN and MAX values of any integer data type can be computed without using any library functions as below and same logic can be applied to other integer types short, int and 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));
    
    0 讨论(0)
  • 2020-11-29 18:45

    You'll want to use limits.h which provides the following constants (as per the linked reference):

    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
    

    Where U*_MIN is omitted for obvious reasons (any unsigned type has a minimum value of 0).

    Similarly float.h provides limits for float and double types:

    -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
    

    You should read the article on floats.h carefully, though float and double can hold the prescribed minimum and maximum values but the precision with which each type can represent data may not match what it is you're trying to store. In particular, it's difficult to store exceptionally large numbers with extremely small fractions attached. So float.h provides a number of other constants that help you to determine if a float or a double can,in fact,represent a particular number.

    0 讨论(0)
提交回复
热议问题