#define THIRD(A,i,j) A[i + (j-i)/3]
or you might try an inline function
inline int third(int *A, int i, int j) { return A[i + (j-i)/3]; }
THIRD(foo,a,b) = 4" will compile,
but not "third(foo,a,b) = 4"
int gcd(int u, int v)
{
if (v == 0)
return u;
return gcd(v,u%v);
}
#define PI 3.14159then following that macro, each occurrence of the text "PI" gets replaced with the text "3.14159" prior to compilation. Macros with patterns allow for something akin to functions. For example:
#define FOO(a,b) 0 < a && a < b && b < 1
if (FOO(1 - x*y, x + y) ---becomes---> if(0 < 1 - x*y && 1 - x*y < x + y && x + y < 1)
#define ODD(a) a & 1
int main()
{
int x,y,n;
cin >> x >> y >> n;
cout << (x + y*ODD(n))
<< endl;
}
This totally doesn't work. If x=3,y=4,n=5
we get
3 + 4*5 & 1... and precdence ruins the whole thing. |
#define ODD(a) (a & 1)
int main()
{
int x,y,n;
cin >> x >> y >> n;
cout << (x + y*ODD(n))
<< endl;
}
The extra parens fix the problem.
|
#define DIVIDES(a,b) (!(b%a))
int main()
{
int x,y;
cin >> x >> y;
cout << DIVIDES(x,y+1)
<< endl;
}
We got the outer parens, but there's still trouble,
because we have an expression in the second slot, so
we get
(!(y + 1%x))... and once again precedence gets us! |
#define DIVIDES(a,b) (!((b)%(a)))
int main()
{
int x,y;
cin >> x >> y;
cout << DIVIDES(x,y+1)
<< endl;
}
We put each "argument" to the macro in enclosing
parens to ensure that it doesn't mess with the
expression we're generating.
|
inline int divides(int a, int b) { return !(a % b); }
Note that this also makes the function implicitly
static meaning that each compilation unit (file)
can have its own definition, as opposed to a regular
functions which allow only one definition for the whole program.
#define LEXLESS(a1,a2,b1,b2) ((a1) < (b1) || (a1) == (b1) && (a2) < (b2))
int main()
{
int x,y,u,v;
cin >> x >> y >> u >> v;
cout << LEXLESS(x,y,u,v) << endl;
}
This performs flawlessly; does exactly what we expect.
Moreover, LEXLESS works great with any type that
defines < and ==, so this work too:
double x,y,u,v;
cin >> x >> y >> u >> v;
cout << LEXLESS(x,y,u,v) << endl;
|
char x,y,u,v;
cin >> x >> y >> u >> v;
cout << LEXLESS(x,y,u,v) << endl;
|
string x,y,u,v;
cin >> x >> y >> u >> v;
cout << LEXLESS(x,y,u,v) << endl;
|
In other words, macros are generic. They produce code that work with any type that supports the operators that appear in the macro. In that sense, a regular old inline function is less powerful, since we would be forced to choose a type for the arguments. Of course C++ offers templates as a mechanism for producing generic code without resorting to macros:
<template T>
inline bool lexless(T a1,T a2,T b1,T b2) { return a1 < b1 || a1 == b1 && a2 < b2; }
At any rate, here's the final thing about this macro: let's use it slightly differently
#define LEXLESS(a1,a2,b1,b2) ((a1) < (b1) || (a1) == (b1) && (a2) < (b2))
int f(int k) { cout << "gotcha!" << endl; return k; }
int main()
{
int x,y,u,v;
cin >> x >> y >> u >> v;
cout << LEXLESS(f(x),f(y),f(u),f(v)) << endl;
}
|
> ./a.out 3 5 4 1 gotcha! gotcha! 1 > ./a.out 4 1 3 5 gotcha! gotcha! gotcha! gotcha! 0 > ./a.out 3 5 3 6 gotcha! gotcha! gotcha! gotcha! gotcha! gotcha! 1 |
LEXLESS(f(x),f(y),f(u),f(v))
literally becomes
#define LEXLESS(a1,a2,b1,b2) ((f(x)) < (f(u)) || (f(x)) == (f(u)) && (f(y)) < (f(v)))So if
f(x) < f(u), short-circuit evaluation
ensures we never evaluate anything else. If f(x) > f(u),
we evaluate the (f(x)) < (f(u)) and get false,
the evaluate (f(x)) == (f(u)) and get false
again, at which point short-circuit evaluation takes over
again. Notice we evaluated f(x) twice and f(u) twice.
Finally in the other case we get six evaluations. Clearly,
arguments to macros get evaluated differently than arguments
to functions: at least functions in C/C++/Java/Scheme.
delay and a function
force that allow one to pass unevaluated
expressions around:
> (define foo (begin (display "Evaluating (+ 4 8)\n") (+ 4 8))) Evaluating (+ 4 8) > foo 12 > (define bar (delay (begin (display "Evaluating (+ 4 8)\n") (+ 4 8)))) > bar #<promise> > (force bar) Evaluating (+ 4 8) 12 > (force bar) 12 > bar #<promise!12> >Notice that (+ 4 8) gets evaluated when foo is defined. However, due to the
delay in the definition of
bar, (+ 4 8) is not evaluated there. The result of the
definition of bar is a "promise", i.e. an unevaluated form.
To get the value you pass it to force. You can
see from the printout that the first time you do this, (+ 4 8)
is evaluted, while each subsequent time the value is simply
remembered, not recomputed.