Declare function as non-static and implement as static inline - c

I want to write different implementations for my function, some inline and some not. Thus, I want to declare the function as:
// MyHeader.h
int myFunc(void);
#if DO_INLINE
static inline int myFunc(void) { return 42; }
#endif
And then also have:
// MySource.c
#if !DO_INLINE
#include "myHeader.h"
int myFunc(void) { return 42; }
#endif
I'll specify DO_INLINE at compile time.
MSVC has no problems with this, but GCC (4.1.1) complains that I'm declaring a static function after I've already declared it as non-static. If I remove the static qualifier, and #include "MyHeader.h" from more than one compilation unit, it will complain about multiple definitions. (As if the inline functions are extern.) I don't quite understand why the compiler has problems with this.
I think this should be pretty obvious and unambiguous:
int myFunc(void);
static inline int myFunc(void) { return 42; }
It shouldn't require the declaration to be static.
That said, there is a solution to my problem that I'm trying very hard to avoid:
#if DO_INLINE
#define MAYBE_STATIC static
#else
#define MAYBE_STATIC
#endif
MAYBE_STATIC int myFunc(void);
EDIT: Here is a more realistic use case for this: http://codepad.org/OkC0Su3v

This header.h should work:
// MyHeader.h
#if DO_INLINE
static inline int myFunc(void) { return 42; }
#else
int myFunc(void);
#endif

Figured it out closely enough. The implementation should be defined as "extern inline" instead:
// MyHeader.h
int myFunc(void);
#if DO_INLINE
extern inline int myFunc(void) { return 42; }
#endif
The compiler will inline this function where it sees fit, but still compile it once as a function, to make it available for linking. That part I don't need, but it doesn't really hurt.

Related

Converting to function to noop

So I have this code:
#ifdef FEATURE
void foo(void);
#endif //#ifdef FEATURE
main {
#ifdef FEATURE
foo();
#endif //FEATURE
}
I'm just wondering if there is more elegant to write this. I was thinking about doing something like this
#ifdef FEATURE
void foo(void);
#else
static inline foo() {
}
#endif //#ifdef FEATURE
That way the compiler should just remove that bit of code out of there and keep the main code cleaner.
Just wondering if there is a better solution out there?
You can do it like this:
#ifdef FEATURE
void foo (void) { }
#else
#define foo()
#endif //#ifdef FEATURE
int main () {
foo();
return 0;
}
if there is a better solution out there?
No. And the solution is perfectly fine and doesn't need anything better.
Some prefer to drop inline specifier as it is only a hint to the compiler and just static void foo(void) {}. (But inline specifier silences -Wunused-function warning on gcc, so I'll say use it).

Two versions of same function: inline and normal?

I'd like to inline some functions, however, they are shared across the team and I don't want to force people to use them.
What would be the best way to add inline versions?
// normal
int func1();
int func2();
// inline versions
inline int inl_func1() { ... }
inline int inl_func2() { ... }
Would something like that make sense?
Edit:
Ideally:
I wouldn't have to write the same function definitions (function body) twice.
It would all be handled with s single define.
Declare/define the inline version and declare the non-inline version in the header file with different names.
// "func.h"
// normal
int func1(void);
int func2(void);
// inline versions
static inline int func1_inline(void) { ... }
static inline int func2_inline(void) { ... }
This allows a user to use either form or both. There is little compelling reason to use the same name and only allow one form.
Both can be handy for code that needs speed vs. space on some calls and not others.
This has a benefit that the one .c file that defines/implements func1(), func2() can use simple code to insure equivalent functionality.
#include "func.h"
int func1(void) {
return func1_inline();
}
int func2(void) {
return func2_inline();
}
BTW, declaring a function like int func1(); does not mean the same as int func1(void);. int func1(); means func1 returns an int, but provids no information about what can be passed to it. It is more like pseudo-code int func1(...);
Perhaps you could tell the people who want the inline functions to define a specific macro before including your header file:
#define WANT_INLINE_FUNC1
#include "awesome_funcs.h"
People who want the to call the externally linked function should omit the macro:
#include "awesome_funcs.h"
Then, in "awesome_funcs.h":
#ifdef WANT_INLINE_FUNC1
inline int func1(int param)
{
/* function body here */
}
#else
extern int func1(int param);
#endif
You also need to define a copy of the function with external linkage in one of your library files, e.g. in "awesome_funcs.c":
#define WANT_INLINE_FUNC1
#include "awesome_funcs.h"
/*
* This will define func1 with external linkage,
* but the function body is copied from the inline definition
* in "awesome_funcs.h".
*/
extern int func1(int param);
EDIT 1
You could combine this with chux's answer and get the best of both worlds (unless that makes things too confusing for your users). Just replace func1 in "awesome_funcs.h" with the following:
static inline int inl_func1(int param)
{
/* function body here */
}
#ifdef WANT_INLINE_FUNC1
inline int func1(int param)
{
return inl_func1(param);
}
#else
extern int func1(int param);
#endif
Then inl_func1 will always be the inline version, and func1 may or may not be inline, depending on whether or not the WANT_INLINE_FUNC1 macro was defined before including "awesome_funcs.h".
What would be the best way to add inline versions?
Your easiest course of action would be to declare static inline versions of these functions:
static inline int func1() { ... }
static inline int func3() { ... }
The function names do not need to differ from those of the corresponding external functions. However, if you #include a header that has declarations of functions with those names, then they must be compatible, AND there must be prior static declarations. For example:
static inline int func1(/* params */);
static inline int func3(/* params */);
#include "our_functions.h"
// ...
static inline int func1(/* params */) {
// implementation ...
}
static inline int func3(/* params */) {
// implementation ...
}
This will allow you to add inline versions without modifying your existing code that calls the external versions of these functions, and without affecting any other translation units. There is at least one alternative, but I don't see anything to recommend it over the above for your particular circumstances.

How to enforce an API definition with macros or some other mechanism?

I have a C header file as part of an API that I am developing which exposes a number of functions. For example:
api.h
void foo();
int bar(char * foobar);
Now, most functions that I expose are actually defined within the API, however, there are some that I leave to the using-developer to implement herself. To make it easier for the developer and enforce conformance to my API I added the following macros:
api.h(modified)
#define DEFINE_FOO() \
void foo()
void foo();
#define DEFINE_BAR() \
int bar(char * foobar)
int bar(char * foobar);
to be used as follows:
implement.c
#include "api.h"
DEFINE_FOO() {
// Codez
}
DEFINE_BAR() {
// More codez
}
One of the things that bothers me about this approach is that the developer will use the DEFINE_* macros but not necessarily intuit that a function, namely "bar" takes arguments. Is there a way to improve this approach or is there a better approach to enforcing custom API definitions in C? Thanks!
There's really no need to use macros and I'd recommend against it (and I've done plenty of "crazy" things with macros over the [last 35+] years).
If you're defining the API, this implies that you're putting [ANSI] prototypes in api.h for all your functions. That doesn't mean you will implement them--it only means that you define the architecture/API. Any function that doesn't have a prototype in api.h isn't part of the API [obviously].
If you do that, the compiler will flag any mismatches. Simply require that the developer include the api.h at the top.
Here's an api.h:
void foo(void);
int bar(char *foobar);
A well conforming .c will compile cleanly:
#include "api.h"
#include <stdio.h>
void
foo(void)
{
}
int
bar(char *str)
{
return 0;
}
A non-conformant .c will not compile correctly:
#include "api.h"
#include <stdio.h>
void
foo(int x)
{
printf("foo: %d\n",x);
}
int
bar(char *str)
{
return 0;
}
You'll get compilation errors:
bad.c:5:1: error: conflicting types for ‘foo’
foo(int x)
^
In file included from bad.c:1:0:
api.h:2:6: note: previous declaration of ‘foo’ was here
void foo(void);
^
So, if a developer makes a mistake, the ordinary code definitions will handle it.
I wouldn't really recommend your approach, but you can technically make it work.
You can pass arguments into macros as such:
#define DEFINE_BAR(arg) \
int bar(char* arg)
Now the programmer can call
DEFINE_BAR(arg_name) {
return strlen(arg_name);
}
This will be turned into the following by cpp:
int bar(char* arg_name) {
return strlen(arg_name);
}

Linker error inline function

I got some compiler/linker errors and i don't know what is the correct method to proceed. I'm in this situation:
a.h: in this file is defined a function declared as "inline", for example: inline void foo1();
b.h: in this file is defined a function declared as "inline" that calls foo1(): inline void foo2();
main.c: there are some functions calls of both foo1 and foo2().
Now, if i declare foo1 and foo2 in a.h and b.h as extern inline void i got the following error:
prj/src/b.o: In function foo1': (.text+0x0):
multiple definition offoo1'
prj/src/main.o:(.text+0x0): first defined here make: *
[kernel] Error 1
What is the way which allow to compile and link without errors/warning in the situation i described?
From http://gcc.gnu.org/onlinedocs/gcc/Inline.html:
When an inline function is not static, then the compiler must assume
that there may be calls from other source files; since a global symbol
can be defined only once in any program, the function must not be
defined in the other source files, so the calls therein cannot be
integrated. Therefore, a non-static inline function is always compiled
on its own in the usual fashion.
In other words, without static, it emits a symbol for your inline function. If you happen to define that function in a header and include it in more than one compilation unit, then you end up with multiple (redefined) symbols. If you want to include the definition in the header, you should make it static.
I tried it and didn't get any errors
a.h
extern inline void foo1()
{
return;
}
b.h
extern inline void foo2()
{
foo1();
return;
}
main.cpp
#include "a.h"
#include "b.h"
int main() {
foo1();
foo2();
return 0;
}
Put the inline definitions in your .h file and in the .c files force an external definition.
For example:
// File: a.h
inline void foo1(void) { /*...*/ }
// File main.c
#include "a.h"
extern inline void foo1(void);
int main(void)
{
/*...*/
}
You may consider using header guards to prevent redefinition. The implementation of the files is as follows. I tried compilation for the following files using CMake and it worked without any problem.
a.h
#ifndef A_H
#define A_H
inline
void foo1()
{
return;
}
#endif
b.h
#ifndef B_H
#define B_H
#include "a.h"
inline
void foo2()
{
foo1();
return;
}
#endif
main.cpp
#include "a.h"
#include "b.h"
int main() {
foo1();
foo2();
return 0;
}

Function macro that evaluates to zero and can be used as a statement

We have a function macro #define FOO(arg) foo(arg) with int foo(const char* bar);. When NDEBUG is defined FOO is defined as #define FOO(arg) 0, however this causes many compiler warnings because in many cases FOO's return value is not used. The solution should work with with ANSI C compilers and cause no warnings. I've tried:
(void)0: can't be assigend to variable
static int foo(const char* bar) { return 0; } : causes unused static function warning in some modules
static inline int foo(const char* bar) { return 0; } : only works with C99 compilers
Thanks for your help!
edit1:
It's somewhat like a trace macro and used all over the project. Mostly it's just used as a statement like FOO("function x called");, but in a few cases I saw if (FOO("condition a")) { /* some more debug output */ }. With NDEBUG defined and optimization enabled nothing should be left of FOO. I didn't come up with this, but I have to clean up this mess :).
edit2: I should add that for gcc release builds these flags are used: -O3 -Wall -ansi
edit3: For now I'm going with __inline int dummy() { return 0; }. __inline works with both VisualC and GCC in ansi mode.
I guess it's a little bit compiler dependent but this should work:
#ifndef NDEBUG
#define FOO(arg) foo(arg)
#else
#define FOO(arg) ((int)0)
#endif
It prevents the "expression has no effect" warning, it does nothing and its value when used is still 0.
EDITED
It seems it's something not so portable so (now) you have these conditions:
(0) or ((int)0) work at least on VC 2010.
__noop should work on any version of VC after 2003.
VC6 is not a problem because it doesn't emit the C4555 warning at all. For other compilers you may use:
((void)0, 0) It may work on a lot of compilers (maybe it's the more portable one?).
inline int foo(const char* bar) { return 0; } works with any other C99 compiler (as you wrote you may need to declare it as static on gcc).
For any other prehistoric C compiler use the solution pointed by #Jobs: abs(0)
What you could do to prevent the warning is the following:
#ifndef NDEBUG
#define FOO(arg) foo(arg)
#else
#define FOO(arg) abs(0)
#endif
I'm not saying this is ideal (you'd have to make sure stdlib.h is included everywhere, for example) but it does prevent the warning.
I'd do something that is dependent on the C version. In the header file:
#if __STDC_VERSION__ > 199900L
inline int foo(const char* bar) { return 0; }
#else
int foo(const char* bar);
#endif
in one compilation unit
#if __STDC_VERSION__ < 199900L
int foo(const char* bar) { return 0; }
#else
int foo(const char* bar);
#endif
or use for the oldish C version something like Job's answer, that is a function that is certain to be optimized out but that doesn't produce the warning.

Resources