MIN and MAX in C

2019-06-17 09:55发布

在哪里MINMAX在C中定义,如果在所有?

什么是实现这些,因为一般地和尽可能安全地输入的最佳方式? (编译器扩展/主流编译器内建优选的。)

Answer 1:

在哪里MINMAX在C中定义,如果在所有?

他们不是。

什么是实现这些,作为一般和类型安全的,最好的方式(编译器扩展/主流编译器内建的首选)。

随着功能。 我不会使用像宏#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))特别是如果你计划部署你的代码。 无论是写自己的,使用类似标准fmaxfmin ,或使用固定宏海湾合作委员会的typeof (你的类型安全奖励太):

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

大家都说:“哦,我知道约一倍的评价,这是没有问题的”,并在几个月在路上,你会被调试几个小时的最愚蠢的问题。

注意使用的__typeof__代替typeof

如果你正在写一个头文件包含在ISO C程序时必须工作,写__typeof__代替typeof



Answer 2:

它也是在GNU libc中(Linux)的和了sys / param.h中的FreeBSD版本提供,并且具有通过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.

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

源库所在的位置:

  • GNU C库
  • FreeBSD的


Answer 3:

有一个std::minstd::max的C ++,但据我所知,有一个在C标准库中没有等价物。 你可以自己定义他们像宏

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

但是,这会导致如果你写类似的问题MAX(++a, ++b)



Answer 4:

避免使用非标准的编译器扩展,并实现它在纯标准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)有两个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;
}


Answer 5:

我不认为他们是标准化的宏。 有浮点已经标准化的功能fmaxfmin (和fmaxf的花车,以及fmaxl长期双打)。

只要你是知道的副作用/双评估的问题,您可以实现它们作为宏。

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

在大多数情况下,你可以把它留给编译器,以确定你正在试图做的和最好的它可以优化它是什么。 虽然像使用时,这会导致问题MAX(i++, j++)我怀疑是在检查的最大增加值的一气呵成不断太大必要。 增量第一,然后检查。



Answer 6:

这是一个迟到的回答,由于一个相当新的发展。 由于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_type是C ++ 11的有限形式的auto 。 它不能(或不应该?)在C ++使用的代码,但没有很好的理由不使用的优良类型推理能力auto使用C ++ 11时。

这就是说,我认为有使用此语法时,包括在宏观没有问题extern "C" { ... }范围; 例如,从C头。 据我所知,该扩展还没有找到它的方式信息铛



Answer 7:

我写了这个版本 ,对于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


Answer 8:

如果你需要的最小/最大,以避免昂贵的分支,你不应该使用三元运算符,因为它会降低编译为一个跳跃。 下面的链接描述用于实现一个最小值/最大值功能没有分支的一种有用的方法。

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



Answer 9:

我知道这家伙说,“C” ......但是,如果你有机会,使用C ++模板:

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

类型安全,并与其他意见提到++没有问题。



Answer 10:

值得指出我认为,如果你定义了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)


Answer 11:

貌似Windef.h (一拉#include <windows.h>maxmin (小写)宏,这也遭受“双评估”困难,但他们在那里为那些不想重新推出自己的:)



Answer 12:

的两个整数的最大ab(int)(0.5((a+b)+abs(ab))) 这也可能与工作(double)fabs(ab)双打(类似的花车)



Answer 13:

与布雷特·黑尔的评论 , clang开始支持__auto_type 2016年左右(见补丁 )。



Answer 14:

最简单的方法是将其定义为一个全局函数.h文件,并调用它,只要你想,如果你的程序是模块化的,大量的文件。 如果不是这样, double MIN(a,b){return (a<b?a:b)}是最简单的方式。



文章来源: MIN and MAX in C