宏功能的不需要的(或不稳定的)结果

时间:2015-01-19 00:18:06

标签: c macros

下面的输入2,3和10的代码用于给出12.5作为结果。([sum(2,3,10)(= 15)+最大(2,3,10)(= 10 )] /最小(2,3,10)(= 2)) 但它输出了2.000作为结果,这是不必要的和错误的。我是在做出优先级错误还是我犯了什么样的错误?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#define MIN( a, b ) ( ( a < b ) ? (a) : (b) ) // Why are the parantheses imporant?
#define MAX( a, b ) ( ( a < b ) ? (b) : (a) )
#define LARGEST( a, b, c ) ( MAX( a, b ) < c ) ? c : ( MAX( a, b ) )
#define SMALLEST( a, b, c ) ( a < MIN( b, c ) ) ? a : ( MIN( b, c ) )
#define SUM( a, b, c ) ( (a + b + c) )
#define EXPR( a, b, c ) ( (LARGEST( a, b, c ) + SUM( a, b, c ) ) /  SMALLEST( a, b, c ) ) 

int main(){
    float a, b, c;
    printf("Enter three integers!\n");
    scanf(" %f", &a);
    scanf(" %f", &b);
    scanf(" %f", &c);
    printf("The result is %f.\n", EXPR(a, b, c));   
    return 0;
}

2 个答案:

答案 0 :(得分:8)

查看预处理器生成的实际代码只执行此命令

gcc -E main.c 

我们将得到(只是最后一个命令输出的最后一部分)

#include <stdio.h>

int main()
{
    float a, b, c;
    printf("Enter three integers!\n");
    scanf(" %f", &a);
    scanf(" %f", &b);
    scanf(" %f", &c);
    printf("The result is %f.\n", ( (( ( ( a < b ) ? (b) : (a) ) < c ) ? c : ( ( ( a < b ) ? (b) : (a) ) ) + ( (a + b + c) ) ) / ( a < ( ( b < c ) ? (b) : (c) ) ) ? a : ( ( ( b < c ) ? (b) : (c) ) ) ));
    return 0;
}

这有点复杂

 ( (( ( ( a < b ) ? (b) : (a) ) < c ) ? c : ( ( ( a < b ) ? (b) : (a) ) ) + ( (a + b + c) ) ) / ( a < ( ( b < c ) ? (b) : (c) ) ) ? a : ( ( ( b < c ) ? (b) : (c) ) ) )

我的第一个猜测就是我在评论中说的是优先级

所以让我们在/运算符中取左操作数并暂时忽略其余操作以查看问题

(( ( ( a < b ) ? (b) : (a) ) < c ) ? c : ( ( ( a < b ) ? (b) : (a) ) ) + ( (a + b + c) ) )
                                        |-----------------------------------------------|
                                            the sum of the three operator will be added to the statement of the false condition ONLY (which is if a  or b is the largest in this case) first and then we will evaluate the ?: because as you know the + is higher than ?: in table precedence 

所以让我们调用左边的块(刚好在上面) LeftBlock 来简化下一次分析

因此结合/运算符的右操作数(或整个语句中剩下的内容),我们将得到

LeftBlock / ( a < ( ( b < c ) ? (b) : (c) ) ) ? a : ( ( ( b < c ) ? (b) : (c) ) )

现在/的优先级高于?:运算符,因此首先会对此表达式进行求值

LeftBlock / ( a < ( ( b < c ) ? (b) : (c) ) ) ? a : ( ( ( b < c ) ? (b) : (c) ) )
|--------------------------------------------| 
          this is the condition for the ?: operator instead of only ( a < ( ( b < c ) ? (b) : (c) ) ) which is WRONG 

正如您所看到的,缺少括号会导致不良后果!!

还有许多关于宏的缺陷,你应该避免从link查看其中的一些!

最后我觉得我对这个问题进行了反混淆! :)

答案 1 :(得分:3)

因为宏扩展会替换宏textualy的每个发生,例如考虑这个简单的宏

#define SQR(x) x * x

此宏使用时

double x = SQR(1.0 + 2.0);

将扩展为

double x = 1.0 + 2.0 * 1.0 + 2.0;

如果添加括号5.0,它们也将被插入

#define SQR(x) (x) * (x)

然后它会扩展到

double x = (1.0 + 2.0) * (1.0 + 2.0);

产生9.0