在哪里MIN
和MAX
在C中定义,如果在所有?
什么是实现这些,因为一般地和尽可能安全地输入的最佳方式? (编译器扩展/主流编译器内建优选的。)
在哪里MIN
和MAX
在C中定义,如果在所有?
什么是实现这些,因为一般地和尽可能安全地输入的最佳方式? (编译器扩展/主流编译器内建优选的。)
在哪里
MIN
和MAX
在C中定义,如果在所有?
他们不是。
什么是实现这些,作为一般和类型安全的,最好的方式(编译器扩展/主流编译器内建的首选)。
随着功能。 我不会使用像宏#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
特别是如果你计划部署你的代码。 无论是写自己的,使用类似标准fmax
或fmin
,或使用固定宏海湾合作委员会的typeof (你的类型安全奖励太):
#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)的和了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))
源库所在的位置:
有一个std::min
和std::max
的C ++,但据我所知,有一个在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的隐式类型促销的常见问题?:
运营商平衡彼此的第二和第三个操作数。 例如,结果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;
}
我不认为他们是标准化的宏。 有浮点已经标准化的功能fmax
和fmin
(和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 ++使用的代码,但没有很好的理由不使用的优良类型推理能力auto
使用C ++ 11时。
这就是说,我认为有使用此语法时,包括在宏观没有问题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
我知道这家伙说,“C” ......但是,如果你有机会,使用C ++模板:
template<class T> T min(T a, T b) { return a < b ? a : b; }
类型安全,并与其他意见提到++没有问题。
值得指出我认为,如果你定义了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)
貌似Windef.h
(一拉#include <windows.h>
的max
和min
(小写)宏,这也遭受“双评估”困难,但他们在那里为那些不想重新推出自己的:)
的两个整数的最大a
和b
是(int)(0.5((a+b)+abs(ab)))
这也可能与工作(double)
和fabs(ab)
双打(类似的花车)
与布雷特·黑尔的评论 , clang
开始支持__auto_type
2016年左右(见补丁 )。
最简单的方法是将其定义为一个全局函数.h
文件,并调用它,只要你想,如果你的程序是模块化的,大量的文件。 如果不是这样, double MIN(a,b){return (a<b?a:b)}
是最简单的方式。