[C][Macro] min max
『목차』
1. The old C macro way
2. The new improved gccㆍclang "statement expression" way
3. [C++] std::min() & std::max()
4. 출처
1. The old C macro way
매크로 원형
/* min */
#define min(a, b) (((a) < (b)) ? (a) : (b))
/* max */
#define max(a, b) (((a) > (b)) ? (a) : (b))
단점 : double-evaluation side effect 발생
/* Input */
#include <stdio.h>
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))
int main(int argc, char * argv[]) {
int a = 2, b = 3;
printf("%d\n", min(a, b));
printf("a : %d b : %d\n\n", a, b);
printf("%d\n", max(a, b));
printf("a : %d b : %d\n\n", a, b);
printf("%d\n", min(a++, b++)); // a++은 2번, b++은 1번 계산되어, a=4 b=4 가 된다.
printf("a : %d b : %d\n\n", a, b);
printf("%d\n", max(a--, b--)); // a--는 1번, b--는 2번 계산되어, a=3 b=2 이 된다.
printf("a : %d b : %d\n\n", a, b);
return 0;
}
/* Output */
2
a : 2 b : 3
3
a : 2 b : 3
3
a : 4 b : 4
3
a : 3 b : 2
min(a++, b++) 혹은 max(a++, b++) 등 매크로 내부에서의 전위ㆍ후위 증감 연산 시, a 또는 b값을 1씩만 증가시키려는 의도와는 다르게, a 또는 b의 값이 2번씩 증감되는 경우가 발생한다.
원문
This technique is commonly used, well-respected by those who know how to use it properly, the "de facto" way of doing things, and fine to use if used properly, but buggy (think: double-evaluation side effect) if you ever pass expressions including variable assignment in to compare:
2. The new improved gccㆍclang "statement expression" way
매크로 원형
/* __typeof__가 정의되어 있는 GCC 및 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; \
})
Using __typeof__ ensures the arguments are evaluated only once, which avoids eg. function call overhead. It's a GCC-specific C extension, C++ gives you function templates as part of the language.
__typeof__ 대신 typeof를 이용할 경우
#define max(a,b) \
({ \
typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; \
})
typeof는 종종 문 표현식과 함께 유용합니다( Statement Expr 참조 ). 다음은 두 가지를 함께 사용하여 모든 산술 유형에서 작동하고 각 인수를 정확히 한 번만 평가하는 안전한 "최대" 매크로를 정의하는 방법입니다.
지역 변수에 밑줄로 시작하는 이름을 사용하는 이유는 a 와 b 로 대체되는 표현식에서 발생하는 변수 이름과의 충돌을 피하기 위해서 입니다. 결국, 우리는 범위가 초기화 이후에만 시작되는 변수를 선언 할 수있는 새로운 형태의 선언 구문을 설계하려고 합니다. 이는 이러한 충돌을 방지하는, 보다 안정적인 방법입니다.
GCC(GNU 컴파일러)에서의 __typeof__ 예제 (GCC = GNU Compiler Collection)
#include <stdio.h>
#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y))
#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; \
})
int main(int argc, char* argv[]) {
int a = 5;
int b = 3;
printf("Smaller value (not safe): %d\n", MIN(a, b));
printf("a: %d, b: %d\n", a, b);
printf("Smaller after ++ (safe): %d\n", min(a++, ++b));
printf("a: %d, b: %d\n", a, b);
printf("Smaller after ++ (not safe): %d\n", MIN(a++, b++));
printf("a: %d, b: %d\n", a, b);
int c = 7;
int d = 8;
printf("Larger value: %d\n", max(c, d));
return 0;
}
원문
This technique avoids the above "double-evaluation" side effects and bugs, and is therefore considered the superior, safer, and "more modern" GCC C way to do this. Expect it to work with both the gcc and clang compilers, since clang is, by design, gcc-compatible (see the clang note at the bottom of this answer).
BUT: DO watch out for "variable shadowing" effects still, as statement expressions are apparently inlined and therefore do NOT have their own local variable scope!
Note that in gcc statement expressions, the last expression in the code block is what is "returned" from the expression, as though it was returned from a function. GCC's documentation says it this way:
The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct. (If you use some other kind of statement last within the braces, the construct has type void, and thus effectively no value.)
3. [C++ ] std::min() & std::max()
[C++][header][algorithm] min max
『목차』 0. 설명에 앞서 1. Default Constructor 2. Custom Constructor 3. Initializer List Constructor 0. std::min & std::max 『설명에 앞서』 참고 1. ①비교할 값들이 많거나, ②ArrayㆍVector와 같은 일련의 컨테이너에
lumir.tistory.com
c++에서의 min max 함수의 활용은 위 링크를 참고하자.
4. 출처
https://betterembsw.blogspot.com/2017/07/dont-use-macros-for-min-and-max.html
https://stackoverflow.com/questions/3437404/min-and-max-in-c/3437442#3437442
https://stackoverflow.com/questions/3437404/min-and-max-in-c