如何编写独立于类型说明符的标准 C(C89 或 C99 兼容)宏?
具体来说,我想编写一个宏来比较两个可以是有符号类型或无符号类型的数字,8 位、16 位、32 位、64 位。
我正在寻找的是这样的:
int c, a , b;
uint16_t p, q, r;
.
.
.
c = min(a, b);
.
.
.
r = min(p, q);
.
.
.
即,相同的宏“min”可用于比较两个整数——任何宽度,有符号或无符号。
我知道一个可以工作的基本宏可以这样写:
#define min(x, y) (x) < (y) ? (x) : (y)
但这涉及两次评估表达式 'x' 和 'y' 的副作用,这是我不想要的。
为了鲁棒性,表达式必须只计算一次。
到目前为止,我的方法似乎是这样的:
#define min(type, x, y) ( { \
type __tmp1 = (x); \
type __tmp2 = (y); \
__tmp1 < __tmp2 ? __tmp1 : __tmp2; } )
int a, b, c;
uint16_t p, q, r;
.
.
.
c = min(int, a, b);
C 编译器抛出错误:“expecting ; found (”,以及许多其他错误。
我怎样才能重新编写这个宏,以便使用这种形式:
<result> = min( <type>, <parm1>, <parm2> );
似乎可以编写“min”宏,使其用法为:
min( <result>, <type>, <parm1>, <parm2> );
但最好有第一种形式。
2012 年 9 月 4 日更新#1:
谢谢你们,您的答案/评论中提供的所有信息使我对可能性有了更广泛的了解。好吧,我没有使用 gcc,我的编译器也不支持 C11 规范,所以似乎唯一可用的选项是:
使用这种形式的宏:
// min( <result>, <type>, <parm1>, <parm2> ); #define min(result, type, x, y) { \ type __tmp1 = (x); \ type __tmp2 = (y); \ result = __tmp1 < __tmp2 ? __tmp1 : __tmp2; } int p, q, r; . . . min(r, int, p, q);
另一种方法是:
inline char min_char(char x, char y) { return x < y ? x : y; } inline short min_short(short x, short y) { return x < y ? x : y; } inline int min_int(int x, int y) { return x < y ? x : y; } inline long min_long(long x, long y) { return x < y ? x : y; } inline unsigned char min_uchar(unsigned char x, unsigned char y) { return x < y ? x : y; } inline unsigned short min_ushort(unsigned short x, unsigned short y) { return x < y ? x : y; } inline unsigned int min_uint(unsigned int x, unsigned int y) { return x < y ? x : y; } inline unsigned long min_ulong(unsigned long x, unsigned long y) { return x < y ? x : y; } #define min(type, x, y) min_##type(x, y) int p, q, r; . . . r = min(int, p, q);
第二种方法是否有任何副作用,在某些情况下可能会产生意想不到的结果,特别是关于“短”和“字符”类型 - 有符号或无符号。
欢迎任何改进或建议。
编辑:
用户将如何指定以下功能:
'min_uchar'
他/她必须写:
r = min(uchar, p, q);
有没有其他方法可以编写函数'uchar',以便用户可以简单地编写:
r = min(unsigned char, p, q);
在这种情况下,我不能将函数命名为“min_unsigned char”,因为它在 C 中是不允许的。是否有任何其他方式或用户必须在宏“min”中将类型指定为“uchar”而不是“unsigned char” '。
2012-09-10 更新:
谢谢大家的帮助。由于我需要接受答案,因此我接受Eitan T的回答,但我感谢大家的回复。谢谢。