Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: New exception DCL37-EX0.

...

Note the comment declaring the macro unsafe as a warning for programmers. Alternatively, the macro can be renamed ABS_UNSAFE() to make it painfully apparent that the macro is unsafe.

Compliant Solution

However, a preferable, compliant solution is to declare ABS() as an inline function. (See PRE00-C. Prefer inline or static functions to function-like macros and PRE12-C. Do not define unsafe macros.)

...

This solution eliminates the problem of recalling which macros are safe and which are not. Unlike the ABS() macro which operates on operands of any type, the abs() function only accepts arguments of type int. Since C doesn't provide C11 provides a way to overload functions on expressions with arguments of different types, but C99 provides no such mechanism. Consequently, there is no way to achieve such genericity using the facilities of the standard C99 language. However, some C implementations provide extensions that make it possible to solve the original problem without using functions. For example, GCC's Statement Expressions along with the __typeof extension make it possible to declare and assign the value of the macro operand to a temporary of the same type and perform the computation on the temporary, thus guaranteeing that the operand will be evaluated exactly once. It should be noted that relying on such extensions makes code non-portable and goes against guideline MSC14-C. Do not introduce unnecessary platform dependencies. 

Code Block
bgColor#ccccff
langc
#define ABS(x)   ({ __typeof (x) __tmp = x; __tmp < 0 ? -__tmp : __tmp; })

It should be noted that relying on such extensions makes code non-portable and goes against guideline MSC14-C. Do not introduce unnecessary platform dependencies.

This code also falls under exception DCL37-EX0 of rule DCL37-C. Do not declare or define a reserved identifier.

This code is also potentially unsafe if it were invoked with a variable named __tmp. Such calling code would constitute a geniuine violation of DCL37-C. Do not declare or define a reserved identifier. This is considered an acceptable problem, as C provides no mechanism to declare a variable in a scope that is guaranteed to be distinct from all other variables in the same scope.

Exceptions

PRE31-EX1: An exception can be made for invoking an unsafe macro with a function call argument provided that the function has no side effects. However, it is easy to forget about obscure side effects that a function might have, especially library functions for which source code is not available; even changing errno is a side effect. Unless the function is user-written and does nothing but perform a computation and return its result without calling any other functions, it is likely that many developers will forget about some side effect. Consequently, while this exception is allowed, it is not recommended.

...