C에서 MIN과 MAX


299

C에서 어디에 MIN있고 MAX정의되어 있습니까?

일반적으로 가능한 한 안전하게 입력하는 가장 좋은 방법은 무엇입니까? (주류 컴파일러를위한 컴파일러 확장 / 내장 선호)

답변:


392

C에서 어디에 MIN있고 MAX정의되어 있습니까?

그렇지 않습니다.

일반적으로 유형을 최대한 안전하게 구현하는 가장 좋은 방법은 무엇입니까?

기능으로. #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))특히 코드를 배포하려는 경우 와 같은 매크로를 사용하지 않습니다 . 직접 작성하거나 standard 또는와 같은 것을 사용 fmax하거나 GCC 문 표현식 에서 GCC의 typeof (typesafety 보너스를 얻음)를 fmin사용하여 매크로를 수정하십시오 .

 #define max(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a > _b ? _a : _b; })

모두들 "오, 나는 이중 평가에 대해 알고있다. 아무 문제가 없다"고 말하고 몇 달 동안 길을 가다 보면 가장 어려운 문제들을 몇 시간 동안 디버깅하게 될 것이다.

__typeof__대신에 typeof다음을 사용하십시오 .

ISO C 프로그램에 포함될 때 작동해야하는 헤더 파일을 작성하는 경우 __typeof__대신 대신 작성하십시오 typeof.


68
gcc가 다음과 같이 경고를 표시하면 매우 유용 할 것입니다.warning: expression with side-effects multiply evaluated by macro
caf

23
@ caf : 전처리기에 C 구문에 대한 더 복잡한 지식이 필요하지 않습니까?
dreamlax

3
알아 내려고 노력한 후에도 VC ++ 에서이 작업을 수행 할 방법이 없다고 생각하지만 최선의 방법은 MSVC ++ 2010 새 decltype키워드 를 엉망으로 만드는 것입니다. 그러나 Visual Studio는 매크로에서 복합 명령문을 수행 할 수 없습니다 (그리고 decltype어쨌든 C ++입니다), 즉 GCC의 ({ ... })구문이므로 어쨌든 불가능하다는 것을 확신합니다. 이 문제와 관련하여 다른 컴파일러를 보지 못했습니다. 죄송합니다. Luther : S
David Titarenco

7
@ dreamlax 나는 누군가가 MAX(someUpperBound, someRandomFunction())임의의 값을 상한으로 제한 하는 경우를 보았습니다 . 그것은 끔찍한 아이디어 였지만 사용하지 않았기 때문에 MAX이중 평가 문제가 있었기 때문에 처음 평가 된 것과 다른 임의의 숫자로 끝났습니다.
Zev Eisenberg

8
@Soumen 예를 들어, MIN(x++, y++)전처리기를 호출 하면 다음 코드가 생성됩니다 (((x++) < (y++)) ? (x++) : (y++)). 그래서, xy두 배 증가합니다.
Antonio

91

또한 GNU libc (Linux) 및 FreeBSD 버전의 sys / param.h에서 제공되며 dreamlax에서 제공하는 정의를 가지고 있습니다.


데비안에서 :

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

FreeBSD에서 :

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

소스 리포지토리는 다음과 같습니다.


위의 답변에서 액세스 할 수있는 시스템의 정의를 추가했습니다 (주석 필드는 내가 알 수있는 한 형식을 허용하지 않습니다). FreeBSD / Linux / glibc 소스 저장소에 대한 링크를 찾으려고합니다.
Mikel

+1. 아주 좋아요 openSUSE/Linux 3.1.0-1.2-desktop/ gcc version 4.6.2 (SUSE Linux) 에도 작동합니다 . :) 휴대용이 아닙니다.
Jack

Cygwin에서도 작동합니다.
CMCDragonkai

1
잠깐만 이중 평가를 방해하지는 않습니까? : 3
1857492

76

C ++ 에는 a std::minstd::maxC가 있지만 C 표준 라이브러리에는 AFAIK가 없습니다. 다음과 같은 매크로로 직접 정의 할 수 있습니다

#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))

그러나 이와 같은 것을 쓰면 문제가 발생합니다 MAX(++a, ++b).


10
왜 대괄호를 너무 많이 넣었습니까 ??? 나는 그들이 #define MIN(A, B) ((A < B) ? A : B)유연한 방법이 아니라고 말한 퀴즈를 찾았습니다 . 왜 ???

78
@Makouda : 매크로에서 괄호를 추가하면 연산자 우선 순위 문제를 피할 수 있습니다. 예를 들어을 고려하십시오 #define MULT(x, y) x * y. 그런 다음로 MULT(a + b, a + b)확장되어 우선 순위에 따라 a + b * a + b구문 분석됩니다 a + (b * a) + b. 프로그래머가 의도 한 것이 아닙니다.
dan04

? 것이이 경우에 필요하지 : 어쨌든 가장 낮은 우선 순위를 가지고
윙어 Sendon을

@ WingerSendon : 그렇지 않습니다. 쉼표 연산자가 수행합니다.
dan04

24

비표준 컴파일러 확장을 피하고 순수 표준 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지원되지 않으면 컴파일러 오류가 발생합니다.

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)two 로 호출 된 경우 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;
}

GENERIC_MAX매크로는 나쁜 생각이지만, GENERIC_MAX(var++, 7)왜 :-) 오늘날 (특히 엄청나게 최적화 / 인라이닝 컴파일러를 사용하여) 매크로를 간단한 형식으로 만 강등 해야하는지 알아 내려고 노력해야 합니다. 함수형 함수는 함수보다 낫고 값 그룹은 열거 형보다 낫습니다.
paxdiablo

21

나는 그들이 표준화 된 매크로라고 생각하지 않습니다. 표준화 이미 부동 소수점을위한 기능이 있습니다 fmaxfmin(와 fmaxf수레를 위해, 그리고 fmaxl긴 복식은).

부작용 / 이중 평가 문제를 알고있는 한 매크로로 매크로를 구현할 수 있습니다.

#define MAX(a,b) ((a) > (b) ? a : b)
#define MIN(a,b) ((a) < (b) ? a : b)

대부분의 경우 컴파일러에 맡겨서 수행하려는 작업을 결정하고 최대한 최적화 할 수 있습니다. 이처럼 사용할 때 문제가 발생하지만 MAX(i++, j++)한 번에 최대 증가 값을 확인해야 할 필요성이 의심 스럽습니다. 먼저 증분 한 다음 확인하십시오.


수학 라이브러리에는 min 및 max 함수가 분명히 있으므로 선호되는 답변이어야합니다. cplusplus.com/reference/cmath/fmax
imranal

@imranal 정확히 무엇에 대해 이야기하고 있습니까? 해당 라이브러리 의 구현 코드는 무엇입니까? 그러나이 코드는 노출 되지 않습니다 . 즉, 라이브러리의 인터페이스에 코드를 배치하지 않아 잠재적으로 안전하지 않을 수 있습니다.
Antonio

@Antonio "노출 된"및 "인터페이스"의 잘못된 정의를 사용하고 있다고 생각합니다. ac 라이브러리의 인터페이스는 헤더 파일의 externed 변수, 유형, 매크로 및 함수 선언입니다. fmin / fmax는 헤더 파일에 선언되어 있으므로 노출되었다고합니다. 안전하지 않은 것으로 귀하가 무엇을 말하는지 잘 모르겠습니다.
rationalcoder

21

이것은 최근의 개발로 인해 늦은 답변입니다. OP가 이식 불가능한 GCC (및 클랜) 확장 typeof또는 __typeof__'깨끗한'ISO C 에 의존하는 대답을 받아들 였으므로 gcc-4.9부터 더 나은 솔루션을 사용할 수 있습니다 .

#define max(x,y) ( \
    { __auto_type __x = (x); __auto_type __y = (y); \
      __x > __y ? __x : __y; })

이 확장의 명백한 이점은 __typeof__솔루션 과 달리 각 매크로 인수가 한 번만 확장된다는 것입니다.

__auto_typeC ++ 11의 제한된 형식입니다 auto. C ++ 코드에서는 autoC ++ 11 을 사용할 때 우수한 형식 유추 기능을 사용하지 않을 이유가 없지만 C ++ 코드에서 사용할 수 없습니다 .

즉, 매크로가 범위에 포함될 때이 구문을 사용하는 데 문제가 없다고 가정 합니다 extern "C" { ... }. 예를 들어 C 헤더에서. AFAIK,이 확장 프로그램은 정보 clang을 찾지 못했습니다


Brett Hale의 의견 과 관련하여 2016 년경 clang부터 지원 __auto_type이 시작되었습니다 ( 패치 참조 ).
Lars

매크로 문제를 인식하는 데 도움이 되긴하지만 여전히 함수가 더 나을 것이라고 생각합니다. :-)
paxdiablo

@paxdiablo-질문에 c-preprocessor태그 가 있지만 동의합니다 . gcc의 __always_inline__속성 과 같은 것을 사용하지 않는 한, 해당 키워드로도 함수가 인라인되도록 보장되지 않습니다 .
Brett Hale

11

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

나는 찬성했지만 대문자 뒤에 밑줄로 시작하는 식별자가 예약되어 있습니다.
dreamlax

8

값 비싼 분기를 피하기 위해 min / max가 필요한 경우 삼항 연산자를 사용하면 안됩니다. 점프로 컴파일됩니다. 아래 링크는 분기없이 최소 / 최대 기능을 구현하는 유용한 방법을 설명합니다.

http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax


1
컴파일러가 충분히 똑똑하다면 지점을 피할 수 있습니다
Axel Gneiting

2
최적화가 켜져 있으면 대부분의 최신 컴파일러는 대부분 분기 대신 조건부 이동을 수행하므로 이와 같은 핵을 사용하는 데는 별다른 의미가 없습니다.
Krzysztof Kosiński

1
당연히, 그때 내가 무엇을보고 있었는지 전혀 모른다. 오랜 시간이 지났다. gcc와 clang은 모두 x86과 armv7a에서 -O가있는 분기를 피합니다.
cib

6

@ 데이비드 Titarenco 여기에 못을 박았다 하지만 좋은 보이게하고, 모두를 보여주기 위해 깨끗한 적어도 약간을 나를 수 있도록 min() 하고 max() 복사하고 여기에 쉽게에서 붙여 만들기 위해 함께. :)

2020 년 4 월 25 일 업데이트 : 또한 C와 C ++를 배우거나 서로 전환하는 사람들을위한 귀중한 비교로서 C ++ 템플릿을 사용하여이 작업을 수행하는 방법을 보여주기 위해 섹션 3을 추가했습니다. 나는이 답을 반복해서 다시 올 수있는 정식 참조로 만들기 위해 철저하고 사실적이며 정확하기 위해 최선을 다했습니다.

1. 오래된 C 매크로 방식 :

이 기술은 일반적으로 올바르게 사용하는 방법, "사실상"일을하는 방법을 잘 알고 올바르게 사용하는 경우 사용하는 것이 좋지만 버그가있는 경우 ( 이중 평가 부작용 ) 생각 하는 사람들이 잘 사용 합니다. 변수 할당포함한 표현식을 전달 하여 비교하십시오.

#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))

2. 새롭게 개선 된 gcc " statement expression "방식 :

이 기술은 위의 "이중 평가"부작용 및 버그를 피하므로,이를 수행하기위한 우수하고, 안전하며 "더 현대적인" 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 문서 는 다음과 같이 말합니다.

복합 명령문의 마지막은 세미콜론 뒤에 오는 표현식이어야합니다. 이 하위 표현식의 값은 전체 구문의 값으로 사용됩니다. (중괄호 내에서 마지막으로 다른 종류의 명령문을 사용하면 구문의 유형이 void이므로 사실상 값이 없습니다.)

3. 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 : Template (C ++)을 참조하십시오 .

그러나 두 max()min()이미의 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있습니다. 이는 입력 매개 변수와 리턴 값이 value가 아닌 참조전달됨을 의미합니다 . 이것은 포인터를 지나가는 것과 같으며 클래스 객체와 같은 큰 유형에 더 효율적입니다. constexpr기능의 일부 수정이 함수 자체 및 함수가 나타내는 수 있어야 컴파일 시간 (최소 제공된 경우에 평가되고 constexpr그것을 컴파일 시간에서 평가 될 수 없다면 디폴트가있는 다시, 입력 파라미터)하지만 다른 일반 기능과 마찬가지로 런타임 평가.

(A)의 컴파일 시간 양태 constexprC ++ 함수는 친절한 컴파일시에 평가가 가능한 경우 그는에서 C 매크로처럼 만드는 constexpr기능이 동일한 것처럼, 컴파일 시간에 수행 될 MIN()또는 MAX()매크로 대체 가능성있을 C 또는 C ++에서도 컴파일 타임에 완전히 평가됩니다. 이 C ++ 템플릿 정보에 대한 추가 참조는 아래를 참조하십시오.

참고 문헌 :

  1. https://gcc.gnu.org/onlinedocs/gcc/Typeof.html#Typeof
  2. https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs
  3. C에서 MIN과 MAX
  4. 2020 년 4 월에 추가 된 추가 C ++ 템플릿 참조 :
    1. ***** Wikipedia : Template (C ++) <-C ++ 템플릿에 대한 추가 정보가 훌륭합니다!
    2. (나 자신의 질문과 답변) 왜`constexpr`이`std :: max ()`에 대한 C ++ 14 템플릿 프로토 타입의 일부입니까?
    3. `constexpr`과`const`의 차이점

위키 백과의 Clang 메모 :

[Clang]은 대부분의 컴파일 플래그 및 비공식 언어 확장을 지원하는 GCC (GNU Compiler Collection)의 드롭 인 대체 역할을하도록 설계되었습니다.


지난 24 시간 동안 침략자에게 : 좋은 소식! 어제 섹션 3에 추가 한 섹션 4 rant를 제거했으며 대신 여기에 넣었습니다 . 좋은 정보를 많이 넣고 모든 혜택을 누릴 수있는 견고하고 도움이되는 정식 답변을 만들기 위해 최선을 다 했으므로 내 답변을 다시 평가하고 원하는 경우 의견을 제시 할 수 있습니다. 이제 다시 초점을 맞췄습니다. :) 감사!
Gabriel Staples

4

내가 생각에서 그 가치를 가리키는 것 당신이 정의하는 경우 그 minmax같은 차 등으로

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

NaN에서는 여전히 작동하지 않습니다. fmin(3.0,NaN)==fmin(NaN,3.0)==fmax(3.0,NaN)==fmax(NaN,3.0)==3.0
greggo

@greggo, 나는 여기에 더 나은 대답을했다 stackoverflow.com/a/30915238/2542702
Z를 보손

4

같은 외모는 Windef.h(라 #include <windows.h>)가 maxmin(소문자) 매크로는 또한 "이중 평가"어려움으로 고통, 그러나 그렇지 않은 사람들을 위해 거기 있음을 다시 롤 자신 :) 원하는


12
당신은 놀랍습니까?
Matt Joiner

2

나는 그 남자가 "C"라고 말한 것을 알고있다. 그러나 만약 당신이 기회가 있다면, C ++ 템플릿을 사용하라 :

template<class T> T min(T a, T b) { return a < b ? a : b; }

다른 주석에서 언급 한 ++에는 문제가 없으며 안전합니다.


16
인수는 const 참조 여야하며 사용자가 전달할 내용을 절대 알 수 없습니다.
nmikhailov 2016 년

6
이러한 기능은 이미 표준화되었습니다 ( std :: min ).
dreamlax

C ++은 대부분의 일반적인 목적을 위해 많은 표준 기능을 가지고 있으며 바퀴를 재발 명하지 마십시오. 그러나 MS는 또한 때때로 문제를 일으키는 자체 최소 / 최대정의합니다
phuclv

0

최대 2 개의 정수 a이며 b입니다 (int)(0.5((a+b)+abs(a-b))). 이것은 또한 작동 할 수 (double)fabs(a-b)복식 (수레 유사)


이것이 잘못된 경우 죄송합니다, 저는 C 초보자이지만이 코드는 저에게 효과적입니다
NRZ

2
정수가 아닌 것으로 확실하지 않습니다. 부동 소수점 수학에는 비선형 정밀도가 있습니다.
Treesrule14

@ Treesrule14의 의견을 확장하려면 : 컴퓨터가 수학자와 같은 방식으로 숫자를 취급하지 않기 때문에 작동하지 않습니다. 부동 소수점에는 반올림 문제가 있으므로 정답을 얻지 못할 수 있습니다. 정수 수학을 사용하더라도 MAX_INT + MAX_INT는 -2를 제공하므로 수식을 사용하는 max (MAX_INT, MAX_INT)는 -1로 나타납니다.
user9876

-3

가장 간단한 방법은 .h파일 에서 전역 함수로 정의하고 프로그램이 많은 파일로 모듈 식인 경우 원할 때마다 호출하는 것입니다. 그렇지 않은 경우 double MIN(a,b){return (a<b?a:b)}가장 간단한 방법입니다.


1
@technosaurus이 솔루션이 왜 잘못된 것이 아니라 그 이유가 설명되어 있으면 도움이 될 것입니다.
Tur1ng

@ technosaurus, 귀하의 답변이 정말 도움이되지 않습니다. Tur1ing에서 함수가 완전히 잘못 정의 된 것으로 보이며 (입력 매개 변수에서 누락 된 유형, return 문 후 세미콜론 누락) int 입력을 double로 변환하는 것은 좋지 않은 방법이므로 유형은 두 배가되어서는 안됩니다. 정의 또는 명령문 표현식이 여기에 더 좋을 것입니다 (예 : here 참조 ) 함수 인 경우 int32_t 유형, uint32_t 유형 및 float 또는 double 유형에 대해 하나의 함수를 만들어 총 3 다른 기능.
가브리엘 스테이플

1
@GabrielStaples이 답변은 답변이 아닌 것으로 표시되어야합니다. 도움이 없습니다. 가장 작은 공간에서 가장 잘못되는 방법의 예로 사용될 수 있습니다. 헤더 (전역 인라인조차도 아님)에서 전역 함수를 권장하면 2 + 컴파일 단위로 코드가 깨지고 컴파일되지 않으며 매크로와 같은 함수의 이름을 지정하며 1989와 같은 int를 암시하며 명시 된 이유없이 더블을 반환합니다. 최선의 경고를 유발하는 캐스트 ... 그리고 가장 중요한 것은 IT가 질문에 대답하지 않습니다-일반적이지 않고 형식이 안전하지 않으며 가장 좋은 방법은 아닙니다
technosaurus

이러한 문제들 각각은 충분히 자세하게 다룰 수없는 추가적인 비판이 필요합니다.
technosaurus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.