C의 MIN과 MAX
어디있나MIN
그리고.MAX
C에 정의되어 있습니까?
이것들을 가능한 한 일반적으로 안전하게 실장하는 가장 좋은 방법은 무엇입니까? (미드레인지 컴파일러용 확장자/빌트인)
어디있나
MIN
그리고.MAX
C에 정의되어 있습니까?
그들은 아니에요.
가능한 한 일반적으로 안전한 타입으로 실장하는 최선의 방법은 무엇입니까(미드레인지 컴파일러용 확장자/빌트인)
기능으로서.저는 이런 매크로를 사용하지 않습니다.#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
특히 코드를 전개할 예정인 경우.직접 쓰거나 표준 또는 와 같은 것을 사용하거나 GCC 문 표현에서 GCC의 타입 오브를 사용하여 매크로를 수정합니다(타입 안전 보너스도 받습니다).
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
모두가 "복수평가에 대해 알고 있습니다. 문제 없습니다."라고 말하고 몇 달 후, 여러분은 몇 시간 동안 계속해서 가장 어리석은 문제를 디버깅하게 될 것입니다.
의 사용에 주의해 주세요.__typeof__
대신typeof
:
ISO C 프로그램에 포함되어 있을 때 동작해야 하는 헤더 파일을 쓰는 경우,
__typeof__
대신typeof
.
이 있습니다.std::min
그리고.std::max
C++, 그러나 AFAIK에서는 C 표준 라이브러리에는 동등한 것이 없습니다.다음과 같은 매크로를 사용하여 직접 정의할 수 있습니다.
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
하지만 만약 당신이 다음과 같은 것을 쓴다면, 이것은 문제를 일으킨다.MAX(++a, ++b)
.
GNU libc(Linux) 및 FreeB에서도 제공됩니다.SD 버전sys/param.h
dreamlax에 의해 제공되는 정의를 가지고 있습니다.
Debian에 대해서:
$ uname -sr
Linux 2.6.11
$ cat /etc/debian_version
5.0.2
$ egrep 'MIN\(|MAX\(' /usr/include/sys/param.h
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
$ head -n 2 /usr/include/sys/param.h | grep GNU
This file is part of the GNU C Library.
프리B로SD:
$ uname -sr
FreeBSD 5.5-STABLE
$ egrep 'MIN\(|MAX\(' /usr/include/sys/param.h
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
소스 저장소는 다음과 같습니다.
@David Titarenco는 여기에 못을 박았지만, 적어도 조금 깨끗하게 하고, 둘 다 보이게 해 주세요.min()
그리고. max()
복사와 붙여넣기를 쉽게 할 수 있습니다.:)
2020년 4월 25일 업데이트: C와 C++를 모두 배우거나 C++에서 다른 템플릿으로 전환하는 사람들을 위한 중요한 비교로서 C++ 템플릿을 사용하는 방법을 보여주는 섹션 3도 추가했습니다.저는 이 답변이 몇 번이고 다시 참조할 수 있는 표준 참고가 되도록 철저하고 사실적이며 올바른 답변을 하기 위해 최선을 다했습니다. 여러분도 저처럼 유용하게 사용하길 바랍니다.
1. 기존 C 매크로 방식:
이 기술은 적절하게 사용하는 방법, "사실상의" 작업 방식을 잘 알고 있는 사람들에 의해 잘 알려져 있으며, 적절하게 사용한다면 사용해도 좋지만, 변수 할당을 포함한 표현들을 비교하기 위해 통과시킨 경우(생각: 이중 평가 부작용)가 발생할 수 있습니다.
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
2. 새롭고 개선된 gcc "표현" 방법:
이 기술은 위의 '이중 평가' 부작용과 버그를 회피하기 위해 우수하고 안전하며 보다 현대적인 GCC C 방법으로 간주됩니다.clang은 설계상 gcc 호환성이 있기 때문에 gcc 컴파일러와 clang 컴파일러 모두 사용할 수 있습니다(이 답변 하단의 clang 노트 참조).
단, "변수 그림자" 효과는 주의해 주십시오.문장의 표현은 분명히 삽입되어 있기 때문에 자체 로컬 변수 범위가 없습니다.
#define max(a,b) \
({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; \
})
#define min(a,b) \
({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; \
})
gcc 스테이트먼트 식에서 코드 블록의 마지막 식은 함수에서 반환된 것처럼 식에서 반환된 것입니다.GCC의 문서에는 다음과 같이 기재되어 있습니다.
compound 스테이트먼트의 마지막은 식 뒤에 세미콜론을 붙여야 합니다.이 서브프레션의 값은 전체 컨스트럭트의 값으로 기능합니다.(괄호 내에서 다른 종류의 스테이트먼트를 사용할 경우 컨스트럭트의 타입은 void이므로 실질적으로 값이 없습니다.)
3. [C++ 한정] C++ 템플릿 방식:
C++ 주의: C++를 사용하는 경우 이러한 유형의 구성에는 템플릿이 권장될 수 있지만, 개인적으로 템플릿을 싫어하며 C++에서도 C스타일을 자주 사용하고 선호하기 때문에 C++에서 위의 구성 중 하나를 사용할 수도 있습니다.
이 섹션은 2020년 4월 25일에 추가되었습니다.
지난 몇 달 동안 C++를 많이 사용했는데, C++ 커뮤니티에서는 가능하면 매크로보다 템플릿을 더 선호해야 한다는 압박감이 매우 강합니다.그 결과 템플릿을 사용하는 능력이 향상되었습니다.완전성을 위해 여기에 C++ 템플릿 버전을 추가해, 보다 정규적이고 철저한 답변을 하고 싶습니다.
기본 기능 템플릿 버전은 다음과 같습니다.max()
그리고.min()
C++에서는 다음과 같이 표시됩니다.
template <typename T>
T max(T a, T b)
{
return a > b ? a : b;
}
template <typename T>
T min(T a, T b)
{
return a < b ? a : b;
}
C++ 템플릿에 대한 자세한 내용은 Wikipedia: 템플릿(C++).
단, 및 는 모두 이미 C++ 표준 라이브러리의 일부입니다.<algorithm>
헤더 (#include <algorithm>
C++ 표준 라이브러리에서는 위의 것과 약간 다르게 정의되어 있습니다.기본 프로토타입:std::max<>()
그리고.std::min<>()
예를 들어, C++14에서는 바로 위의 cplusplus.com 링크에서 프로토타입을 살펴봅니다.
template <class T>
constexpr const T& max(const T& a, const T& b);
template <class T>
constexpr const T& min(const T& a, const T& b);
이 키워드는typename
에일리어스입니다.class
(따라서 사용법은 동일합니다.<typename T>
또는<class T>
C++ 템플릿이 발명된 후 나중에 확인되었으므로 템플릿 타입은 일반 타입일 수 있습니다.int
,float
클래스 유형뿐만 아니라 , 등).
여기에서는, 입력 타입과 반환 타입이 모두 다음과 같이 되어 있는 것을 알 수 있습니다.const T&
이는 "유형에 대한 참조"를 의미합니다.T
". 이는 입력 파라미터와 반환값이 값 전달이 아닌 참조로 전달됨을 의미합니다.이는 포인터를 통과하는 것과 비슷하며 클래스 개체와 같은 큰 유형에 더 효율적입니다.그constexpr
함수의 일부는 함수 자체를 수정하고 함수가 컴파일 시에 평가될 수 있어야 함을 나타낸다(적어도 제공된 경우).constexpr
입력 파라미터) 단, 컴파일 시 평가할 수 없는 경우 다른 일반 함수와 마찬가지로 런타임 평가로 기본 돌아갑니다.
의 constexpr
는 C++의 시간 C-매크로와합니다.constexpr
시 되며, 는 컴파일 시 수행될 입니다.MIN()
★★★★★★★★★★★★★★★★★」MAX()
매크로 대체는 컴파일 시 C 또는 C++에서도 완전히 평가될 수 있습니다.이 C++ 템플릿 정보에 대한 자세한 내용은 아래를 참조하십시오.
4. [C++ ] C++std::max()
C++ 를 사용하고 있는 경우는, 그 기능을 추가해 주세요.<algorithm>
헤더 파일에는 다양한 형식이 있습니다.cppreference.com 커뮤니티 Wiki(https://en.cppreference.com/w/cpp/algorithm/max))에 있는 문서 페이지의 "Possible implementation" 섹션을 참조하여 4가지 형식의 구현이 가능합니다.std::max()
.
통상의 사용법은 다음과 같습니다.
std::max(100, 200);
...하지만 많은 숫자를 한 번에 비교하고 싶다면, 4번째 양식을 사용할 수 있습니다. 4번째 양식을 사용할 수 있습니다.std::initializer_list<T>
이렇게요.
함수 선언:
template< class T, class Compare >
constexpr T max( std::initializer_list<T> ilist, Compare comp );
사용방법:
// Compare **3 or more numbers** by passing a curly-brace-initialized
// `std::initializer_list<>` to `std::max()`!:
std::max({100, 200, 300}); // result is 300
std::max({100, 200, 300, 400}); // result is 400
std::max({100, 200, 300, 400, 500}); // result is 500
std::max({100, 200, 300, 400, 500, 600}); // result is 600
// etc.
참고 자료:
- https://gcc.gnu.org/onlinedocs/gcc/Typeof.html#Typeof
- https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs
- C의 MIN과 MAX
- 2020년 4월에 추가된 C++ 템플릿 참조:
- *****Wikipedia: 템플릿(C++) <-- C++ 템플릿에 대한 훌륭한 추가 정보!
- (나만의 질문과 답변):constexpr이 std::max()의 C++14 템플릿 프로토타입의 일부인 이유는 무엇입니까?
- constexpr과 const의 차이
Wikipedia의 Clang 노트:
[Clang]은 GNU 컴파일러 컬렉션(GCC)의 드롭인 대체로서 기능하도록 설계되어 대부분의 컴파일 플래그와 비공식 언어 확장을 지원합니다.
관련:
나는 그들이 표준화된 매크로라고 생각하지 않는다..fmax
★★★★★★★★★★★★★★★★★」fmin
(그리고)fmaxf
및 floats로용fmaxl
★★★★★★★★★★★★★★★★★★」
부작용/이중평가 문제를 알고 있으면 매크로로 구현할 수 있습니다.
#define MAX(a,b) ((a) > (b) ? a : b)
#define MIN(a,b) ((a) < (b) ? a : b)
대부분의 경우 컴파일러에 맡기고 원하는 작업을 결정하고 최대한 최적화할 수 있습니다. 하면 , 이렇게 쓰면 가 생기죠.MAX(i++, j++)
한 번에 증가하는 값의 최대값을 확인할 필요는 없을 것 같습니다.먼저 증가시킨 다음 확인합니다.
비표준 컴파일러 확장을 피하고 완전 표준 C(ISO 9899:2011)에서 완전한 타입 세이프 매크로로 구현합니다.
솔루션
#define GENERIC_MAX(x, y) ((x) > (y) ? (x) : (y))
#define ENSURE_int(i) _Generic((i), int: (i))
#define ENSURE_float(f) _Generic((f), float: (f))
#define MAX(type, x, y) \
(type)GENERIC_MAX(ENSURE_##type(x), ENSURE_##type(y))
사용.
MAX(int, 2, 3)
설명.
는 MAX를 .type
파라미터를 지정합니다.이 제어 매크로(특정 유형에 대해 구현된 경우)는 두 파라미터가 모두 올바른 유형인지 확인하기 위해 사용됩니다. 경우,type
지원되지 않습니다.이치노
y 중 , x "y" 에 오류가 발생합니다.ENSURE_
매크로를 선택합니다.더 많은 유형이 지원되는 경우 이러한 매크로를 추가할 수 있습니다.구조체나 배열 등이 아닌 산술형(정수형, 플로트형, 포인터형 등)만 사용하는 것으로 상정하고 있습니다.
모든 유형이 올바르면 GENERIC_MAX 매크로가 호출됩니다.각 매크로 파라미터 주위에는 C 매크로를 기술할 때 통상적인 표준 주의사항으로 괄호가 추가로 필요합니다.
그리고 C의 암묵적인 타입의 프로모션에 관한 일반적인 문제가 있습니다.?:
연산자는 두 번째 및 세 번째 피연산자를 서로 균형 있게 조정합니다.예를 들어 다음과 같은 결과가 있습니다.GENERIC_MAX(my_char1, my_char2)
가 될 것이다int
매크로가 잠재적으로 위험한 유형의 프로모션을 수행하지 않도록 하기 위해 의도한 유형의 최종 유형을 캐스팅했습니다.
근거
매크로에 대한 두 매개 변수가 동일한 유형이어야 합니다.둘 중 하나가 다른 유형일 경우 운영자가 다음을 좋아하기 때문에 매크로가 더 이상 안전하지 않습니다.?:
암묵적인 유형의 프로모션을 생성합니다.또, 최종 결과는 항상 위에서 설명한 대로 의도한 타입으로 되돌릴 필요가 있습니다.
하나의 매개 변수만 있는 매크로를 훨씬 더 쉽게 작성할 수 있습니다.그러나 파라미터가 2개 이상인 경우 추가 유형 파라미터를 포함해야 합니다.유감스럽게도 다음과 같은 것은 불가능하기 때문입니다.
// this won't work
#define MAX(x, y) \
_Generic((x), \
int: GENERIC_MAX(x, ENSURE_int(y)) \
float: GENERIC_MAX(x, ENSURE_float(y)) \
)
문제는 위의 매크로가 다음과 같이 호출될 경우MAX(1, 2)
둘로int
, 이 경우, 가능한 모든 시나리오의 매크로를 계속 시도합니다._Generic
어소시에이션리스트그래서...ENSURE_float
매크로도 확장됩니다.비록 매크로는 관련이 없지만int
그리고 그 매크로는 의도적으로만 포함되기 때문에float
타입, 코드가 컴파일되지 않습니다.
이 문제를 해결하기 위해 ## 연산자를 사용하여 프리프로세서 단계에서 매크로 이름을 만들었습니다.그 대신 실수로 매크로가 확장되지 않도록 합니다.
예
#include <stdio.h>
#define GENERIC_MAX(x, y) ((x) > (y) ? (x) : (y))
#define ENSURE_int(i) _Generic((i), int: (i))
#define ENSURE_float(f) _Generic((f), float: (f))
#define MAX(type, x, y) \
(type)GENERIC_MAX(ENSURE_##type(x), ENSURE_##type(y))
int main (void)
{
int ia = 1, ib = 2;
float fa = 3.0f, fb = 4.0f;
double da = 5.0, db = 6.0;
printf("%d\n", MAX(int, ia, ib)); // ok
printf("%f\n", MAX(float, fa, fb)); // ok
//printf("%d\n", MAX(int, ia, fa)); compiler error, one of the types is wrong
//printf("%f\n", MAX(float, fa, ib)); compiler error, one of the types is wrong
//printf("%f\n", MAX(double, fa, fb)); compiler error, the specified type is wrong
//printf("%f\n", MAX(float, da, db)); compiler error, one of the types is wrong
//printf("%d\n", MAX(unsigned int, ia, ib)); // wont get away with this either
//printf("%d\n", MAX(int32_t, ia, ib)); // wont get away with this either
return 0;
}
이것은 꽤 최근의 사태로 인해 늦은 답변입니다.OP가 비포터블 GCC(및 clang) 확장에 의존하는 응답을 받아들였기 때문에typeof
- 또는__typeof__
'깨끗한' ISO C의 경우 - gcc-4.9 현재 더 나은 솔루션을 사용할 수 있습니다.
#define max(x,y) ( \
{ __auto_type __x = (x); __auto_type __y = (y); \
__x > __y ? __x : __y; })
이 확장의 명백한 이점은 각 매크로 인수가 다음과 같이1회만 확장된다는 것입니다.__typeof__
솔루션.
__auto_type
C++11의 제한된 형식입니다.auto
C++ 코드에서는 사용할 수 없습니다(또는 사용해서는 안 됩니다).다만, 다음의 뛰어난 타입 추론 기능을 사용하지 않는 것은 타당하지 않습니다.auto
C++11을 사용하는 경우.
즉, 이 구문을 사용하는 경우 매크로가 이 구문을 사용하는 데 문제가 없을 것으로 생각됩니다.extern "C" { ... }
예를 들어 C 헤더로부터의 스코프.AFAIK, 이 내선번호는 해당 경로 정보를 찾을 수 없습니다.
짚고 넘어가야 할 게 있는데, 만약 당신이 이 문제를min
그리고.max
같은 삼원 수술로
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
같은 결과를 얻기 위해 특별한 경우fmin(-0.0,0.0)
그리고.fmax(-0.0,0.0)
인수를 교환할 필요가 있다
fmax(a,b) = MAX(a,b)
fmin(a,b) = MIN(b,a)
이전 GCC 확장:연산자<?, >?, <?=, >?=
GCC의 매우 오래된 버전에는 연산자가 있었습니다.<?, >?
(여기는 C++로 되어 있었지만, 그 때는 C의 내선번호로도 적용되었다고 생각합니다) 오퍼레이터도 본 적이 있습니다.<?=, >?=
할당 스테이트먼트에 대응합니다.
피연산자는 한 번 평가되었으며 매우 짧은 할당 문에 대해서도 허용되었습니다.일반적인 최소/최대 할당에 비해 매우 짧습니다.이것보다 더 나은 것은 없다.
이것들은 다음의 약어였다.
min(a, b) === a < b ? a : b === a <? b;
max(a, b) === a > b ? a : b === a >? b;
a = min(a, b); === if(b < a) a = b; === a <?= b;
a = max(a, b); === if(b > a) a = b; === a >?= b;
최소값을 찾는 것은 매우 간단하다.
int find_min(const int* ints, int num_ints)
{
assert(num_ints > 0);
int min = ints[0];
for(int i = 1; i < num_ints; ++i)
min <?= ints[i];
return min;
}
언젠가 GCC로 돌아올 수 있기를 바랍니다. 왜냐하면 이 운영자들은 천재적이기 때문입니다.
처럼 보인다Windef.h
(a la.#include <windows.h>
)가 있습니다.max
그리고.min
(소문자) 매크로도 「이중 평가」의 곤란에 시달리고 있습니다만, 독자적인 매크로를 재롤링 하고 싶지 않은 분들을 위해 준비되어 있습니다.
고가의 브랜치를 피하기 위해 min/max가 필요한 경우, 3진 연산자를 사용하지 마십시오.이 연산자는 점프로 컴파일되기 때문입니다.다음 링크에서는 분기하지 않고 최소/최대 함수를 구현하기 위한 유용한 방법을 설명합니다.
http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
최대 2개의 정수a
그리고.b
이(int)(0.5((a+b)+abs(a-b)))
이것은, 와도 동작할 수 있습니다.(double)
그리고.fabs(a-b)
복식용(플로트용)
가장 간단한 방법은 글로벌 함수로 정의하는 것입니다..h
파일이 많은 모듈러형 프로그램이라면 언제든지 호출할 수 있습니다.아니라면,double MIN(a,b){return (a<b?a:b)}
가장 간단한 방법입니다.
그 사람이 "C"라고 한 거 알아요그러나 기회가 있으면 C++ 템플릿을 사용하십시오.
template<class T> T min(T a, T b) { return a < b ? a : b; }
safe 라고 입력하고, 다른 코멘트에 기재되어 있는 ++ 에 대해서는 문제가 없습니다.
MSVC, GCC, C 및 C++에서 동작하는 버전을 작성했습니다.
#if defined(__cplusplus) && !defined(__GNUC__)
# include <algorithm>
# define MIN std::min
# define MAX std::max
//# define TMIN(T, a, b) std::min<T>(a, b)
//# define TMAX(T, a, b) std::max<T>(a, b)
#else
# define _CHOOSE2(binoper, lexpr, lvar, rexpr, rvar) \
({ \
decltype(lexpr) lvar = (lexpr); \
decltype(rexpr) rvar = (rexpr); \
lvar binoper rvar ? lvar : rvar; \
})
# define _CHOOSE_VAR2(prefix, unique) prefix##unique
# define _CHOOSE_VAR(prefix, unique) _CHOOSE_VAR2(prefix, unique)
# define _CHOOSE(binoper, lexpr, rexpr) \
_CHOOSE2( \
binoper, \
lexpr, _CHOOSE_VAR(_left, __COUNTER__), \
rexpr, _CHOOSE_VAR(_right, __COUNTER__) \
)
# define MIN(a, b) _CHOOSE(<, a, b)
# define MAX(a, b) _CHOOSE(>, a, b)
#endif
언급URL : https://stackoverflow.com/questions/3437404/min-and-max-in-c
'programing' 카테고리의 다른 글
Java 8 getter는 옵션타입을 반환해야 합니까? (0) | 2022.08.02 |
---|---|
Vue.js 동적 컴포넌트 및 목록 (0) | 2022.08.02 |
Vuejs Axios 데이터가 표시되지 않음 (0) | 2022.08.02 |
인증 토큰을 VueJ에 저장하는 모범 사례 (0) | 2022.08.02 |
Array List의 특정 위치에서 요소를 업데이트하려면 어떻게 해야 합니까? (0) | 2022.08.02 |