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

什么是最好的方式来实现这些,作为一般和类安全的可能吗?(编译器扩/内置于主流汇编者优先。)

有帮助吗?

解决方案

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

他们不是。

什么是最好的方式来实现这些,作为一般和类安全作为可能的(编译器扩/内置于主流编译器的优选的)。

作为功能。我不会使用宏喜欢 #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)), 尤其是如果计划部署你的代码。要么写你自己,使用什么样的标准 fmaxfmin, 或修复的宏使用 海湾合作委员会的类型 (你得到奖励的类型安全过):

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

每个人都说"哦我知道关于双重评价,这是没有问题"和几个月的道路,您可以试的最愚蠢的问题。

注意使用 __typeof__ 而不是的 typeof:

如果你正在写一个文件,该文件标题 必须工作的时候,包括在ISO C 计划,写信 __typeof__ 而不是的 typeof.

其他提示

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

源存储库在这里:

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

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

但是,这会导致问题,如果你喜欢写东西MAX(++a, ++b)

避免非标准编译器扩展和执行它作为纯标准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.隐式类型优惠的常见问题的?:operator平衡抵靠彼此第二和第三操作数。例如,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;
}

我不认为他们是标准化的宏。存在用于浮点已经,fmaxfmin(和fmaxf为浮筒,和fmaxl长期双打)标准化的功能。

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

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

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

这是一个迟到的回答,由于一个相当新的发展。由于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 ++代码中使用,虽然没有充分的理由不使用C ++ 11时使用auto的优异类型推理能力。

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

我写这篇版本对于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

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

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

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

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

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

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

类型安全,并且与在++其他意见提及。

没有问题

的两个整数ab最大值是(int)(0.5((a+b)+abs(a-b)))。这也可以与(double)fabs(a-b)双打(类似于用于浮子)工作

相关布雷特硬朗的评论clang开始支持2016年左右__auto_type(见的补丁)。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top