Converting to function to noop - c

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).

Related

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);
}

Declare function as non-static and implement as static inline

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.

Fun with C macros

Let's say I have a function macro in C called FOO. There are also two macros called BAR1 and BAR2, which are basically two flavors of the same macro. I'd like to write a macro BAR such that it expands to BAR1 in functions which invoke FOO somewhere before the use of BAR and to BAR2 otherwise. So for example:
void func1(void)
{
FOO();
...
BAR();
}
would be equivalent to
void func1(void)
{
FOO();
...
BAR1();
}
while this function:
void func2(void)
{
BAR();
}
would be equivalent to
void func2(void)
{
BAR2();
}
I'd like to avoid introducing global variables or doing additional checks at runtime. Is this even possible?
Short answer: NO. The C precompiler knows nothing about function limits, so even if you managed to modify the BAR macro as you want it, that would not be limited to the current function anyway.
Now, if you are willing, you can add some checks to the BAR macro. And those checks can be written to be resolved at compile time, so no runtime overhead results.
For example:
extern char _sentinel_[2];
#define FOO() char _sentinel_;
#define BAR() if (sizeof(_sentinel_) == 1) BAR1() else BAR2()
The trick is that the look up of variable _sentinel_ will resolve the global variable or the local one, depending on the use of FOO(). And since the condition in the if is a compiler constant, the compiler will optimize out the other branch.
My attempted hack at using gotos failed because when FOO() isn't used, the jump label is missing for BAR(). But, fear not, I've come up with an even more gross hack.
You can use #includes instead of a macro for FOO() and BAR(). This will allow you absolute control on how the code gets expanded.
/* FOO file */
#define BAR_IS_BAR2
/* whatever code FOO needs to do */
/* BAR file */
#ifdef BAR_IS_BAR2
BAR2();
#undef BAR_IS_BAR2
#else
BAR1();
#endif
/*...in you source code...*/
void func1 () {
#include "FOO"
/*...*/
#include "BAR"
}
void func2 () {
#include "BAR"
}

Can you define a function style macro for conditional compilation?

Is it possible to define a macro called IPHONE_ONLY for conditional compilation that looks like this:
IPHONE_ONLY -(void)myMethod {
//method body
}
or
IPHONE_ONLY( -(void)myMethod {
//method body
})
Even though normally you would surround the function with #ifdef, I tested with gcc and indeed the following also works. I don't know if it is standard:
#ifdef IPHONE
# define IPHONE_ONLY(...) __VA_ARGS__
#else
# define IPHONE_ONLY(...)
#endif
IPHONE_ONLY(int func(void)
{
return 12;
})
I have never seen anyone code like that though. It is quite common to write such a function like this:
#ifdef IPHONE
int func(void)
{
return 12;
}
#endif
Your editor also would be much happier with this, since it understands functions, but not function body used as a macro parameter!
Sure you can, but I don't think that this would make your code more readable
#if on_iphone
# define IPHONE_ONLY(...) __VA_ARGS__
#else
# define IPHONE_ONLY(...)
#endif
and then you can use the macro the 2nd way you have it in your question.
But this is really ugly and against the visual expectations of anybody who is used to read proper C.
I think you are looking for ifdef:
#ifdef IPHONE_ONLY
void myMethod(){
//method body
)
#endif
#ifdef IPHONE_ONLY
# define MY_METHOD() myMethod();
void myMethod() {
......
}
#else
# define MY_METHOD()
#endif
in your c code of your project, you call MY_METHOD().
This will avoid you to call myMethod() in that way each time you need it in your code
for(i=0; i<10; i++) {
// some thing to do here
#ifdef IPHONE_ONLY
myMethod();
#endif
// other thing to do here
}
with the definition above you will call your myMethod(); in this way
for(i=0; i<10; i++) {
// some thing to do here
MY_METHOD();
// other thing to do here
}
If IPHONE_ONLY is defined then the prepocessor will change the macro MY_METHOD() by the call of the function myMethod();
If IPHONE_ONLY is not defined then the preprocessor will change the MY_METHOD() by nothing. It's like the macro call MY_METHOD() does not exist in your code. and the function void myMethod() will not be defined

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