How to inline a function for only release build - c

// common.h
// This is foo function. It has a body.
__inline void foo() { /* something */ }
// a.cpp
#include "common.h" // for foo function
// Call foo
// b.cpp
#include "common.h" // for foo function
// Call foo
I would like to inline the foo function only when I build for release. I don't want to inline functions for Debug build.
I tried it but linker errors annoyed me.
In this case, foo function's body is defined in common.h header file.
so if I just do
//common.h
#if !defined(_DEBUG)
__inline
#endif
void foo() { /* something */ }
It will be met a link error in DEBUG build. Because two modules try to include common.h.
I have no idea to solve it.
Is it possible?

The "easy" solution would be this:
#if !defined(_DEBUG) || defined(NDEBUG)
#define INLINE inline
#else
#define INLINE static
#endif
static is necessary to silence linking errors and get around the One Definition Rule.
A better solution would be to simply disable inlining project wide for debugging. GCC supports the -wno-inline-functions and -fno-inline-small-functions options to counteract those optimizations, and it also does not enable inlining for -O1 or lower (and probably -Os as well). Most compilers have similar options.
I call the latter a better solution because it should instruct the compiler to ignore the inline hint, eliminating the need for pesky preprocessor directives.

The fundamental thing to realize is that the inline keyword (or Microsoft's __inline extension for C - since MSVC doesn't support C99) is essentially a pass to violate the one definition rule. If you think about it - that's all it really is, since the compiler is under no obligation to actually perform any inlining.
So, when you have an inline function you're allowed to have the function defined in more than one module. In fact, you're obligated to have it defined in any module that actually uses the function.
However, if you don't declare the function as inline, you have to ensure that you have no more than one definition (exactly one if it actually gets used). For non-member functions (all function in C), there are a few ways around this:
declare the function as static to change it's linkage to internal (note that you can have static inline functions to begin with).
in C++ you can place them in an anonymous namespace (which has an effect similar to declaring the static)
you can use preprocessor manipulation to handle this. It's kind of ugly, but it works, and I've seen the technique used successfully in the wild. Whether it's worth the effort is another thing altogether - you'll have to decide that yourself.
Basically, what you need to do is have an implementation of the function in a separate .c file, just like if you were following the tradition of a-single-function-per-module coding standard (actually you can do this just as well putting several inline functions in the .c module - but they should all be inline or not inline as a group to keep things from getting too out of hand). The implementation of the function needs to arrange to be able to be included in a header - so it needs include guards, just like any other header. Then you use the preprocessor to conditionally include the implementation as part of the header when you want inline functions (so the implementation will be available to all modules), but don't include it if you're not inlining (so you follow the one definition rule in that case):
The common.h header:
// common.h
#ifndef COMMON_H
#define COMMON_H
#ifdef RELEASE
#define USE_INLINE
#define INLINE __inline
#else
#define INLINE
#endif
INLINE void foo(void);
#ifdef USE_INLINE
#include "foo.c"
#endif
#endif /* COMMON_H */
The implementation of foo():
// foo.c
#ifndef FOO_C
#define FOO_C
#include <stdio.h>
#include "common.h"
INLINE void foo()
{
printf("foo\n");
}
#endif /* FOO_C */
And an example program:
// main.c
#include<stdio.h>
#include "common.h"
int main()
{
foo();
return 0;
}
Now if you compile for release:
cl /DRELEASE main.c foo.c
foo() will be inline (or __inline as the case may be).
If you compile for non-release:
cl test.c foo.c
you have a non-inline foo().
And both the compiler and linker are happy in either case.
All that said, I kind of like the suggestion to maybe redefine INLINE to be static for debugging purposes.
However, ultimately I'm not sure I see the point to any of this really - modern debuggers are able to step through functions that are inline, and the debugger probably won't inline function calls if you disable optimizations. So you can set breakpoints inside the inline function as well and have it work fine in non-optimized builds.
I'm not sure exactly what you're end-goal in this really is. What's the drawback to leaving the functions as inline in debug/non-optimized builds?

#ifdef RELEASE
#define INLINE __inline
#else
#define INLINE
#endif
Then
// common.h
INLINE void foo() { /* something */ }
// a.cpp
#include "common.h" // for foo function
// Call foo
// b.cpp
#include "common.h" // for foo function
// Call foo
then define RELEASE for the release version. of course you can see from this there are lots of ways to do it.

You can't declare header only functions as non-inline. You could declare them as static (a.k.a. C-style static), but that will generate a copy of the function (including local static variables, if any) in each translation unit. A better solution is to leave it as inline. In debug mode when optimizations are disabled compilers usually don't inline any functions.

In most cases release flags are not defined. Typically debug flags are defined.
_DEBUG is defined by most compilers, so there is no need to define a release flag:
More practical:
#ifndef _DEBUG
__inline void foo() { /* something */ }
#else
//some alternative
#endif

Use compiler conditionals and define a compile time flag.
Example:
#ifdef RELEASE_BUILD_FLAG
//Run inline function
#else
//some alternative
#endif

Related

How come the preprocessor directives in my header are not seeing the macro I put above the #include in source? (C code)

I am attempting some conditional compilation for unit testing static functions in C. (roughly following the method outlined in this answer https://stackoverflow.com/a/593437/8347016)
I have it set up like so:
check_blah.c
#define UNIT_TEST 1
#include "blah.h"
#include "testframework.h"
...
blah.h
#if UNIT_TEST
#define u_static
#else
#define u_static static
#endif
...
#if UNIT_TEST
void foo(/* some parameters */)
#endif
blah.c
#include "blah.h"
...
u_static void foo(/*some parameters */) {
/* some definition */
}
...
And just to cover my bases, here is how the files are compiled in make
check_blah: check_blah.c blah.o testframework.o
gcc check_blah.c blah.o testframework.o -o check_blah
blah.o: blah.c blah.h
gcc -c blah.c -o blah.h
testframework.o: /* similar to above */
If I compile check_blah without it having any references to foo, and then run gdb info functions, I see that foo is considered static even though UNIT_TEST is defined. Even more confusing, the compiler somehow does recognize UNIT_TEST as defined. In an experiment I defined a macro, SPEEP to be 10 if UNIT_TEST was defined and 100 otherwise. Then in check_blah.c I set some int to SPEEP and then printed it. It would print 10! So the line #define ustatic MUST be being hit as well, but somehow it isn't since foo remains static.
If I take the line #define UNIT_TEST 1 and move it to the top of blah.h, everything seems to work (i.e, info functions claims foo is not static).
So does anyone know the reason for this awkward (and inconsistent looking) behavior with preprocessor macros and directives?

C - Should Function Implementations in Header use extern/inline/static?

I am using function implementations in a header file for simple code sharing. Minimal example:
foo.h:
#ifndef FOO_H
#define FOO_H
// potentially want to include extern/static/inline keyword for this function
int max(int x, int y) {
return x < y ? y : x;
}
#endif
bar.c:
#include <stdio.h>
#include "foo.h"
int main() {
printf("Max of 1 and 2: %d", max(1, 2));
}
I was suggested to the inline keyword for the functions implemented in the .h file. However, that gives me a linker error. If I use extern inline it does compile, but since I just guessed to try this I am not confident that it isn't dangerous/bad in some way.
Is using extern inline appropriate here? If not, what combination of static, extern, and inline should I use?
If you're going to put the implementation of a function in a header file, it must have the static storage class specifier. This restricts the visibility of the function name to only the translation unit (i.e. .c file) where it is ultimately built-in. Note that doing so means that if multiple source files include this header then each one will have its own copy of the function.
Using inline as well as static is not necessary, but it can serve as a hint to the compiler to perform certain optimizations on it.

Linkage and static function confusion

I read that
A function with internal linkage is only visible to one compilation
unit. (...) A function declared static has internal linkage
For .c files it sorta makes sense, but I was wondering what happens with static functions in headers, which get included by multiple .c files but usually have an include guard.
I was reading this answer about static functions in headers, and the first item mentions that it doesn't create a symbol with external linkage and the second item mentions the function is available purely through the header file. Isn't that contradictory? How can the function be available and at the same time have no external symbol? So I did a little test:
/* 1.h */
#ifndef ONE_H
#define ONE_H
#include <stdio.h>
static void foo() {
printf("foo from 1.h %p\n", foo);
return;
}
void bar();
#endif
/* 1.c */
#include "1.h"
#include <stdio.h>
void bar() {
printf("foo,bar from 1.c %p,%p\n", foo, bar);
foo();
}
/* 2.c */
#include "1.h"
#include <stdio.h>
int main() {
printf("foo,bar from main %p,%p\n", foo, bar);
foo();
bar();
return 0;
}
...
debian#pc:~ gcc 2.c 1.c
debian#pc:~ ./a.out
foo,bar from main 0x400506,0x400574
foo from 1.h 0x400506
foo,bar from 1.c 0x400559,0x400574
foo from 1.h 0x400559
As expected bar is the same across all files, but shouldn't foo be too? Isn't 1.h included only once? Adding inline to foo resulted in the same behavior. I'm kinda lost.
Read here, how a header file basically works. That should clarify about your actual question.
Briefly: A header file is just inserted instead of the corresponding #include directive. So any declarations or definitions are treated by the compiler as if you actually copy/pasted the text into your file.
Anyway, you should be careful with function definitions in a header. This is deemed bad style in general. It blows the code for instance, creating redundant copies of that function. Also Function pointers cannot be compared (you never know ...). It is often better to bundle the functions into a library with just the declarations in a header (non-static then: external linkage). There are good justifications sometimes, however (no rule without exceptions). One of them are inline functions.
-static functions are functions that are only visible to other functions in the same file (more precisely the same translation unit).
Check this article for a detailed explanation on linkage: http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html

Can I change attributes from a symbol (function) in another c-File?

I try to keep this as simple as I can (even tho I have a relating question running, but this is supposed to be more general.
When I declare a function extern void foo(void) with a prototype and call it in the same C-File, can I give it the attribute weak in another C-File?
The reason is this: Whether the extern function foo() is implemented depends on some build options and may OR may not be added to the binary. If it is not, I get (obviously) an error undefined reference. This is why I want to declare it weak (with __attribute__((weak)) from GCC or with #pragma weak. For some reason (to long to explain here) I want to do this in a seperate C-File, without adding the #pragma/attribute to the original declaration? - Is there anyway to do this? If I just add #pragma weak foo to anothr C-File it won't work. ( I am using GCC 4.8.1 )
//edit: as requested some code:
Note: The implementation of foo is not linked to the project
Function.c
extern void foo(void);
// #pragma weak foo <-- If I add it here, it links without problems
void bar(void)
{
foo();
}
WeakDeclaration.c
#pragma weak foo <-- If I add it here, I get undefined reference error
//edit2:
Ok I gonna try so specify my question a bit more - is there any way to make the symbol foo globally visible to the linker with the attribute weak from within another C-File (WeakDeclaration.c)
You can switch the pragma using an included header and macro commands:
Function.c:
#include "weak.h"
...
extern void foo(void);
#ifdef TURN_ON_WEAK
#pragma weak foo
#endif
weak.h:
#ifndef MY_WEAK_H
#define MY_WEAK_H
#define TURN_ON_WEAK
#endif

How to "undeclare" a function prototype or hide a function prototype or #uninclude a header

I would like to have function A() call B() as an inline macro, but I don't want B() to be visible to the world. I only want A() visible and if the user uses B() accidentally, I want a compiler error.
I know how to do it without inlining:
// a.h
void A(void);
// a.c
#include "b.h"
void A(void) { B(); }
If I #include "a.h", then I have access to A() but not B(). That's fine; that's what I want.
Now I want to do the same, but reduce one level of call complexity by inlining B into A, but I want to hide B.
// a.h
#include "b.h"
#define A() B()
#uninclude "b.h" <----This is bogus, but I want the equivalent.
// main.c
#include "a.h"
A(); <-- ok
B(); <-- undefined function
This is for low-level firmware, where the call overhead does make a difference but I don't want to abandon high-level code management just for efficiency. In C++, this is trivial, but I am looking for cpp hacks to do it in pure C.
(In my case, a represents a HAL and b represents a BSP. The HAL is processor specific, while the BSP is board (PCB) specific)
If the only declaration b.h makes is a declaration of B and not a definition, then you can do this in a.h:
// a.h
static inline void A(void)
{
#undef _B__H_ //need this if you have more than one of these inline declarations
#include "b.h"
B();
}
assuming b.h looks like this:
// b.h
#ifndef _B_H_
#define _B_H_
void B(void);
#endif
Then the declaration of B is in scope only within A.
In a.c, be sure to include b.h before a.h (or do #undef _B_H_ to force reloading b.h). Otherwise, you will get warnings or errors about incompatible scopes. (a.h includes b.h at local scope, while a.c includes b.h at file scope then ignores all of the remaining local scope includes.)
This will also work if b.h makes additional declarations, as long as they are acceptable in the scope of a function body.
If you do this:
#define B A
#include "b.h"
#undef B
This changes the definition of B in "b.h" to be a definition of A instead. This requires that b.h define B, not just declare it, so that might not be what you want.
Then after that, in the file where those lines appear, code can use A (with calls such as A()), but no declaration of B is in scope. So attempts to use B would result in compiler errors. (Other declarations made in b.h would be in scope.)
#define A() (B)()
#define B() syntax error
People who write B() will get a syntax error reported (in some shape or form).
People who write A() will generate a call to (B)(), which is OK.
This does not stop someone writing (B)() in the code, of course, but it is 80% of the way there.

Resources