我的C宏在做什么?

时间:2019-02-18 20:14:54

标签: c

#include <stdio.h>
#include <stdlib.h>

#define MAXIMUM(a,b) (a>b ? a:b)
#define MAX(a,b,c) (MAXIMUM(MAXIMUM(a,b),c))
#define MINIMUM(a,b) (a<b ? a:b)
#define MIN (a,b,c) (MINIMUM(MINIMUM(a,b),c))
#define MID(a,b,c) (MAX(a,b,c)+ MIN(a,b,c))/2


int main()
{
    int a=0; int b=0; int c=0;
    scanf("%d",&a);
    scanf("%d",&b);
    scanf("%d",&c);
    float t = MID(a,b,c);
    printf("%f\n",t);
    return 0;
}

我得到的错误是

left operand of comma has no operator in #define MID(a,b,c)
The expression cannot be used as a function in #define MIN

3 个答案:

答案 0 :(得分:6)

哦!我知道您的问题是什么

#define MIN (a,b,c) (MINIMUM(MINIMUM(a,b),c))

应该是

#define MIN(a,b,c) (MINIMUM(MINIMUM(a,b),c))

预处理器对空格敏感; MIN令牌与其参数列表(a,b,c)

之间不能有空格

答案 1 :(得分:1)

按原样使用宏存在一些问题。宏背后的想法是使编码更简单,但是因为没有类型检查,这充满了危险:

问题-没有类型检查:

#include <stdio.h>

#define max(a,b)  ((a) > (b) ? (a):(b))
int main()
{
    int a = -1;
    unsigned int b = 2;
    printf("The max is: %d\n", max(a,b));

    return 0;
}

输出相当不确定。 gcc输出-1

问题-双重评估

如果您的宏参数不是简单变量,则会发生双重评估:

#include <stdio.h>

#define max(a,b)  ((a) > (b) ? (a):(b))

int main() {
     int a = 1, b = 2;
     printf("max(%d, %d) = %d\n", a, b, max(a, b));
     printf("max(%d, %d) = %d\n", a, b, max(a++, b++));
     printf("max(%d, %d) = %d\n", a, b, max(a, b));
     return 0;
 }

如果您正在查看mid(a,b,c),那就更糟了。

结论

请不要编写这样的代码。

如果您坚持使用没有 non-standard typeof运算符的编译器,则最好使用stdtypes.h和stdint.h并声明函数:

#define __declare_min(__type) __inline__ static __type min_ ## __type(__type a, __type b) { return a < b ? a : b;  } 

__declare_min(uint32_t)
__declare_min(int64_t)

,您可以显式使用它们:

int main() {
     printf("%u", min_uint32_t(3, -5));
     printf("%d", min_int64_t(-1, -5));
} 

如果您的编译器具有typeof类型的运算符,则可以使用:

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

GCC特定

如果您使用的是足够新版本的gcc(如果您使用的是gcc,则有可能),您应该使用__auto_type而不是typeof

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

每gcc类型的手册页} 1

使用__auto_type代替typeof有两个优点:

  1. 宏的每个参数在扩展中仅出现一次 宏。这阻止了宏扩展的大小增长 当对此类宏的调用嵌套在参数中时呈指数增长 这样的宏。

  2. 如果宏的参数已可变地修改 类型,使用__auto_type时它只会被评估一次,如果使用__auto_type则会被评估两次 使用typeof。

C ++

那是另一回事:-)

答案 2 :(得分:0)

在MIN之后删除空格,应该为:

#define MIN(a,b,c) (MINIMUM(MINIMUM(a,b),c))

有效。