14

In most cases if I want to create an optional feature in C, I simply create two functions like this:

#ifdef OPTIONAL_SOMETHING
void do_something(int n, const char *s)
{
    while (n--) {
        printf("%s", s);
    }

    /* ...You might get the point, really do something... */
}
#else
void do_something(int n, const char *s)
{
    /* Empty body */
}
#endif

So if the symbol is undefined — when the feature is disabled — an empty function is compiled into the executable.

Delving into the assembly listing, it seems that GCC compiles and calls the empty functions when the optimizations are disabled. If the optimizations are enabled, also with -O2 and -O3, it compiles only the necessary stack handling code, but it optimizes out the call instructions. All in all it keeps the function.

About the same applies for the non-empty, but unused methods.

It should simply throw out the whole thing, but it does not. Why it is the default behavior? And just for curiosity: How I can eliminate this?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Ákos Kovács
  • 502
  • 1
  • 10
  • 23
  • "If the optimizations enabled, also with -O2 and -O3 it compiles only the necessary stack handling code, but it optimize-out the call instructions." Does this mean there's still some overhead this way? `start_timer();do_something();stop_timer();` takes longer than `start_timer();stop_timer();`? – Albert Netymk Oct 28 '13 at 14:26

2 Answers2

27

Since the function has external linkage (is not static), the compiler cannot eliminate it because another object file might reference it. If the function is static, it will be eliminated completely.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 4
    That still leaves the question of why GCC doesn't inline the function body (i.e, omit the call) when the body is known to be empty, though. –  Apr 06 '12 at 22:33
  • 1
    @duskwuff: I've had static functions inlined by the compiler so that I can't set breakpoints on them, even when I'd like to. It might depend on the version of GCC or the platform though. Otherwise, I don't know; I've not been involved in the development of GCC and am not privy to the decisions made on such issues. – Jonathan Leffler Apr 06 '12 at 22:35
  • 1
    You got me curious so I just tried this myself: I'm on gcc 4.4.5 and with -O3 (only) I don't see empty functions being called (whether static or not). – timday Apr 06 '12 at 23:22
  • 2
    No, they not called they just exist. (Debian GCC 4.4.5-8). – Ákos Kovács Apr 06 '12 at 23:27
  • 5
    The *compiler* cannot eliminate them because it's unknown whether they are used at translation time. Only the linker could eliminate them, but this is only possible if the compiler has been instructed (via a special `-f` option whose name I forget) to put each function in its own section, and if the linker has been told to garbage-collect unreferenced sections. – R.. GitHub STOP HELPING ICE Apr 06 '12 at 23:33
  • @R.. I believe [this](http://embeddedfreak.wordpress.com/2009/02/10/removing-unused-functionsdead-codes-with-gccgnu-ld/) is what you are describing. However, is there one optimization that makes `// before;empty_function();//after` and `//before;//after;` the same? This `empty_function()` is defined in other C file, if it matters. – Albert Netymk Oct 28 '13 at 14:37
1

If you want the compiler to eventually inline the function you got to tell him. Declare your function inline, this allows the compiler not to emit the function if it sees fit.

Now this may lead to an "undefined symbol" error when you compile with -O0 or so. Put an "instantiation" like

void do_something(int n, const char *s);

in just one compilation unit (.c file).

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177