C++宏(最小最大值)无法正常工作

she*_*hek 2 c++ macros

为什么以下代码不起作用?它打印INT_MAX.但是如果我取消注释内部for循环中的两行,那么它工作正常(打印2).我不能像这样组合两个宏?不确定是否需要进一步的细节...非常自我解释.

谢谢.

#include <iostream>
#include <limits.h>

using namespace std;

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

int main(int argc, char **argv)
{
    int N = 100;
    int *drop = new int[N+1];
    drop[0] = 0; drop[1] = 1; drop[2] = 1;
    for(int i=3; i<=N; i++)
    {
        drop[i] = INT_MAX;
        for(int start=1; start<=i; start++)
        {
            drop[i] = min(drop[i], max(start, drop[i-start]+1));
            //int x = max(start, drop[i-start]+1);
            //drop[i] = min(drop[i], x);
        }
    }
    cout<<drop[3]<<endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

sam*_*gak 7

在宏中的术语周围加上括号:

#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
Run Code Online (Sandbox Code Playgroud)

事实上,这个:

drop[i] = min(drop[i], max(start, drop[i-start]+1));
Run Code Online (Sandbox Code Playgroud)

正在扩展到这个(没有括号):

drop[i] < start > drop[i-start]+1 ? start: drop[i-start]+1 ? drop[i] : start > drop[i-start]+1 ? start: drop[i-start]+1;
Run Code Online (Sandbox Code Playgroud)

可能无法按照您的预定顺序进行评估.使用括号强制执行正确的操作顺序.

如注释中所述,如果宏参数被多次计算,则不应对具有副作用的表达式使用宏.

  • @Michael:仅仅因为宏可能是危险的并不意味着他们错了.你应该知道自己在做什么. (2认同)

Shr*_*han 7

C++已经具有std::min与std::max所限定<algorithm>.您可以将代码更改为纯C++版本

#include <iostream>
#include <algorithm>
#include <limits>
using namespace std;

int main(int argc, char ** argv) {
    int N = 100;
    int * drop = new int[N + 1];
    drop[0] = 0;
    drop[1] = drop[2] = 1;
    for (int i = 3; i <= N; ++i) {
        drop[i] = numeric_limits<int>::max();    // <limits>
        for(int start = 1; start <= i; ++start)
            drop[i] = min(drop[i], max(start, drop[i - start] + 1));    // <algorithm>
    }
    cout << drop[3] << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*ael 6

这不是一个答案,而是对所有开发人员的恳求:请不要使用这样的宏.C++为这些目的提供了模板功能.请记住,宏只是替换参数而不是预先评估它们.即使你在samgak解释时添加括号,这只能解决问题的一半.考虑这样的代码:

int x = 5;
int y = max(++x, 0);
Run Code Online (Sandbox Code Playgroud)

打电话者会期待x=6并y=6在那之后; 然而宏将被用于

int y = (++x > 0)? ++x : 0;
Run Code Online (Sandbox Code Playgroud)

导致x=7和y=7.

  • @ArkadiuszDrabczyk,速度不是一件小事:对于生产软件速度可能是成功与失败的区别.除此之外,懒惰评估值不限于速度.考虑像`if(ptr!= NULL &&*ptr!='\n'){...}`这样的东西,它可以按照惰性求值的方式工作,但如果`&&`不懒,可能会导致段错误. (2认同)