...
Code Block |
---|
|
#define ABS(x) (((x) < 0) ? -(x) : (x))
void f(int n) {
int m;
m = ABS(++n); /* undefined behavior */
/* ... */
}
|
The invocation of the ABS()
macro in this noncompliant code example expands to the following code. Since the resulting expression modifies an object more than once, its behavior is undefined. (See EXP30-C. Do not depend on order of evaluation between sequence points.)The resulting code has well-defined behavior, but causes n
to be incremented twice rather than once, which may be surprising to those unfamiliar with the implementation of the macro, or unaware of the fact that they are using a macro in the first place.
Code Block |
---|
|
m = (((++n) < 0) ? -(++n) : (++n)); /* undefined behavior */
|
Anchor |
---|
| cs_inline_function |
---|
| cs_inline_function |
---|
|
...
A possible and preferable compliant solution is to define an inline function with equivalent but safe unsurprising semantics:
Code Block |
---|
|
inline int Abs(int x) {
return x < 0 ? -x : x;
}
|
...
Code Block |
---|
|
#define ABS(x) ({int__typeof (x) tmp = (x); tmp < 0 ? -tmp : tmp; })
|
...