0

How can I use #define to say that one value consists of the sum of two other values. Would it be allowed and good practice in C to do something like this?

#define VALUE_A 2
#define VALUE_B 2
#define SUM_A_B (VALUE_A + VALUE_B)

If not, what should I do to achieve this functionality?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user2426316
  • 7,131
  • 20
  • 52
  • 83
  • 5
    It works and I do it all the time. – kenny Nov 30 '13 at 15:11
  • It would be interesting to write a small program with this in it (it is valid and looks reasonable - just as long as you remember the parentheses) then look at the compiled code. I am 99% sure the compiler will evaluate the sum into a simple constant so there is no performance penalty at runtime. Anyone care to check? – Floris Nov 30 '13 at 15:58
  • [BOOST_PP_ADD](http://www.boost.org/doc/libs/1_41_0/boost/preprocessor/arithmetic/add.hpp) – BLUEPIXY Nov 30 '13 at 16:58
  • 2
    @Floris: The compiler is required to *be aware* that it's a constant expression, because there are different rules about where you can and cannot use non-constant expressions (or where semantics are different based on whether you have a constant expression). There's nothing that requires it to actually evaluate the value at compile-time, but it would be gratuitously stupid not to do so. – R.. GitHub STOP HELPING ICE Nov 30 '13 at 17:33

2 Answers2

2

The Linux and GCC header files do it routinely, if that's a vote of confidence. e.g.:

$ grep -r 'define.*+' /usr/include/
...
/usr/include/linux/fdreg.h:#define FD_STATUS    (4 + FD_IOPORT )
...
/usr/include/linux/elf.h:#define PT_GNU_STACK   (PT_LOOS + 0x474e551)
...
/usr/include/i386-linux-gnu/asm/unistd_32.h:#define __NR_timer_settime  (__NR_timer_create+1)

etc.

Tim Pierce
  • 5,514
  • 1
  • 15
  • 31
1

If you just need that for integer constants (type int) you may use enumerations for this type of constants

enum { SUM_A_B = (VALUE_A + VALUE_B), };

possible advantages:

  • the sum is only evaluated once by the compiler. This is not a big deal for modern compilers if this is only such a simple sum, but could make a small difference when you are using more complicated expressions
  • even nowadays compiler errors and debugging information isn't that good for values coming from the preprocessor. Enumeration constants usually can be traced well.

A disadvantage is that the value itself is not accessible in the preprocessor itself. So you can't do #if/#else constructs with it. But you could at least still define it as

#define SUM_A_B SUM_A_B

So #ifdef/#else constructs would still work.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • That's a slightly modified form of the discussion in [`static const` vs `#define` in C](http://stackoverflow.com/questions/1674032). – Jonathan Leffler Nov 30 '13 at 15:44