3

I understand how each works, but I was curious if one or the other actually is more efficient memory-wise. #define seems to be used all the time in the embedded C world, but I am wondering if it is actually justified over a const most of the time.

If one is more efficient than the other, does anyone have some way to test and show this?

greatwolf
  • 20,287
  • 13
  • 71
  • 105
radix07
  • 1,506
  • 1
  • 17
  • 22
  • Please give an example. – code monkey Dec 23 '14 at 20:35
  • Depending on your compiler. Why don't you add a global `const` variable to your program, use it somewhere in your code, and then check the disassembly to see if the compiler refers to it as a variable or replaces it with a fixed value? – barak manos Dec 23 '14 at 20:35
  • 4
    You obviously _don't_ understand how each works. Sorry. – Lightness Races in Orbit Dec 23 '14 at 20:35
  • 1
    Ok... I apologize for not backing up my knowledge of the #define before trying to ask this question, was just trying to keep it simple for now. Saw some points on both sides here http://stackoverflow.com/questions/1637332/static-const-vs-define/1637367#1637367. Thought I would try to flesh out a better answer... – radix07 Dec 23 '14 at 20:45
  • @radix07: The highest-rated comment on that answer dispels the myth that writing `#define` allows you to magically avoid using any memory. – Lightness Races in Orbit Dec 23 '14 at 20:53
  • 1
    http://en.wikipedia.org/wiki/Constant_folding – Rapptz Dec 23 '14 at 20:54
  • If there is any difference in memory usage, it's going to be negligible. If you really want to optimize your program, either in terms of its memory footprint or its speed, then you're barking up a very small tree here. Write a program that works, then use run-time analysis tools to find where the bottlenecks are and optimize them. In an embedded system, it's not uncommon to rewrite highly critical functions in assembly code, bypassing the C compiler altogether. – Dan Korn Dec 23 '14 at 21:02
  • 4
    a const only uses memory once, in readonly memory, and it is accessed via code. A #define has its' text inserted at every point where the #define name is used. If the #define value can be incorporated as part of a single machine instruction, then irregardless of how many times it is referenced, it will add less total ram usage that the const, because the const needs code to gen a pointer to it and code to actually retrieve it. However, if the #define cannot be incorporated in a single instruction, then the const can easily take less total ram. So the answer is: "it depends" – user3629249 Dec 23 '14 at 22:41
  • @user3629249 The "a const only uses memory once ..." comment would make an fine answer. – chux - Reinstate Monica Dec 23 '14 at 23:43
  • 1
    Traditionally, embedded device manufacturers supplied their own compiler and it was dreadful at optimizing, so `#define` was preferred in order to save memory. Of course, a `const` variable is not a constant expression so in some cases you do not even have that option. – M.M Feb 04 '15 at 20:09

2 Answers2

5

Let's put #define aside, because it doesn't really exist in your program. The preprocessor takes your macros and expands them before the compiler can even spot that they were ever there.

The following source:

#define X 42
printf("%d", X);

is actually the following program:

printf("%d", 42);

So what you're asking is whether that takes more or less memory than:

const int x = 42;
printf("%d", x);

And this is a question we can't fully answer in general.

On the one hand, the value 42 needs to live in your program somewhere, otherwise the computer executing it won't know what to do.

On the other hand, it can either live hardcoded in your program, having been optimised out, or it can be installed into memory at runtime them pulled out again.

Either way, it takes 32 bits (it may not be 32) and it doesn't really matter how you introduced it into your program.

Any further analysis depends on precisely what you are doing with the value.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
5

It depends on whether you are taking the address of the constant or not. If you do not take the address of the constant, then the compiler has no problem folding it into other computations and emitting it inline (as an immediate or literal), just like the #defined version. However, if you write:

const int c = 42;
const int *pc = &c;

then a copy of c must live in the global .rodata section in order to have its address taken, adding sizeof(int) bytes of Flash space atop any copies the compiler decided to inline; however, the compiler might be able to fetch that constant from memory more cheaply than it can incorporate it as an inline literal, depending on its value and what CPU you're compiling for.

Try compiling some code each way and looking at the resulting assembler listings...

LThode
  • 1,843
  • 1
  • 17
  • 28