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++)). 그래서, x및 y두 배 증가합니다.
— 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::min와 std::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

나는 그들이 표준화 된 매크로라고 생각하지 않습니다. 표준화 이미 부동 소수점을위한 기능이 있습니다 fmax과 fmin(와 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

내가 생각에서 그 가치를 가리키는 것 당신이 정의하는 경우 그 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)

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>)가 max와 min(소문자) 매크로는 또한 "이중 평가"어려움으로 고통, 그러나 그렇지 않은 사람들을 위해 거기 있음을 다시 롤 자신 :) 원하는


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.