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번씩 증감되는 경우가 발생한다.
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; \
})
__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;
}
'프로그래밍 언어 > C++' 카테고리의 다른 글
[C] 피보나치 수열과 메모이제이션 (0) | 2023.09.09 |
---|---|
[C++] min max 함수 (algorithm 라이브러리) (0) | 2023.09.06 |
[C] 문자열에서 공백을 제거하는 함수 (0) | 2023.09.05 |
[C] 재귀함수(Recursive/리쿼시브)의 개념과 공부하는 이유 (0) | 2023.09.05 |
[C++] 공백 포함 문자열 입력받기 (0) | 2023.09.04 |