Program Tip

C에서 데이터 유형의 최소 및 최대 값

programtip 2020. 10. 29. 19:13
반응형

C에서 데이터 유형의 최소 및 최대 값


C에서 데이터 유형 (즉, int, char.etc)의 가능한 최소값과 최대 값을 결정하는 기능은 무엇입니까?


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제한 floatdouble유형을 제공합니다 .

-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.ha float또는 a double캔이 실제로 특정 숫자를 나타내는 지 확인하는 데 도움이되는 여러 가지 다른 상수를 제공합니다 .


"그러나 글리프", "최대 값이 결국 변경 될 수있는 불투명 유형의 최대 값을 결정해야한다면 어떻게해야합니까?" 계속할 수 있습니다. "내가 제어하지 않는 라이브러리의 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-type 표현식 ~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의 제안을 통합하기 위해 답변이 업데이트되었습니다. 둘 다 감사합니다.)


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

표준 c 라이브러리의 일부로 포함 된 limits.hfloat.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;
}

The header file limits.h defines macros that expand to various limits and parameters of the standard integer types.


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

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

참고URL : https://stackoverflow.com/questions/2053843/min-and-max-value-of-data-type-in-c

반응형