I am trying to enable a set of functions from a header only if a macro is defined
I define the macro before including anything and it reaches the .h file and highlights the proper functions, but it does not reach the .c file so I can call the functions with the right prototypes but they have no definition since the .c file does not see I defined the macro
Is there some way to get this to work without having to stuff all of the .c code inside the .h file?
example:
test.h:
#ifdef _ENABLE_
int enabled_function(int a, int b);
#endif
test.c:
#ifdef _ENABLE_
int enabled_function(int a, int b)
{
return a + b;
}
#endif
main.c:
#define _ENABLE_
#include "test.h"
int main()
{
printf("%d", enabled_function(10, 10));
}
you need to use conditional compilation in both header and C file
in header file:
#define SOMETHING
#ifdef SOMETHING
int a(int);
int b(int);
int c(int);
#endif
In the C file:
#include "header_file_with_SOMETHING_declaration.h"
#ifdef SOMETHING
int a(int x)
{
/* ... */
}
int b(int x)
{
/* ... */
}
int b(int x)
{
/* ... */
}
#endif
Your source files test.c and main.c represent separate translation units. The macro definitions declared in one are not visible to the other.
Declarations that need to be visible across multiple translation units, whether of macros or of anything else, generally should go into header files that all translation units wanting them #include. It is possible to have a header that serves the sole purpose of defining macros that control configuration options, that you would create or update prior to compilation. There are tools that automate that sort of thing, but they are probably much heavier than you require for your purposes right now.
For macros specifically, most compilers also offer the option of specifying macro definitions via compiler command-line arguments.
Either way, no, your definition in main.c of macro _ENABLE_ will not be visible in test.c. (And no, you shouldn't merge test.c into test.h.)
But you should also consider whether you actually need any of that. Certainly there are use cases for cross-translation-unit build-time configuration, but what you present does not look like one of them. It is rarely very useful to suppress the compilation of a function just because you know you're not going to call it. it is usually better to either remove it altogether or to leave it, uncalled. In the latter case, your linker might even be smart enough to omit unused functions from the final binary.
"Is there some way to get this to work without having to stuff all of the .c code inside the .h file?"
and from comments...
"...but I wish to be able to define the macro in my main file and have it be visible from the .c file too
So, you are asking to #include one .c file into another .c file. This is doable with caution. But because a .c file containing the main() function cannot be #include into another .c file without invoking a multiply defined symbol error for main(...), it has to be the other way around. That is a dedicated .c file (eg. enabled.c) could be created that contains all of the #defines function prototypes and definitions. This .c file can then be #included into main.c to hopefully satisfy a variation of what you are looking for.
Following is tested source code that does this:
enable.c
#define _ENABLE_
//test criteria - then create prototype of enabled_function
#ifdef _ENABLE_
static int enabled_function(int a, int b);
#endif
#ifdef _ENABLE_
static int enabled_function(int a, int b)
{
return a + b;
}
#endif
static int use_enabled_function(int a, int b);
//This will be created with or without _ENABLE_, but its
//definition changes based on whether _ENABLE_ exists or not.
static int use_enabled_function(int a, int b)
{
#ifdef _ENABLE_
return enabled_function(a, b);
#elif
return -1;
#endif
}
main.c
#include "enable.c"
int main(void)
{
//test criteria - then use enabled_function
#ifdef _ENABLE_ //must include test for existence before using
printf("%d\n", enabled_function(10, 10));
#endif
//no need to test criteria here (tested internally)
printf("%d\n", use_enabled_function(10, 10));
return 0;
}
Related
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.
When I include another source(I.e stdio.h) the preprocessor is smart enough to include only the functions that I am using in my code?
Example: Assuming this small program, would be ease to include only what I am using, and what the printf functions uses, including them recursively, but what about bigger programs?
#include <stdio.h>
int main(void) {
printf("Hello World\n");
return 0;
}
No. On the contrary:
#include performs textual replacement: it opens the file and copies all1 of its contents into your main C file. In the process it executes all preprocessor instructions in the included file. Amongst other things, this means that it will recursively include all files that are #included in the header.
#include does not know and does not care which part of the included file you end up using.
1 As mentioned, preprocessor instructions are executed in the included file. This can modify what gets included. For example, assume the following header file header.h:
#ifndef HEADER_H
#define HEADER_H
#ifdef NDEBUG
# define LOG(...) ((void) 0)
#else
# define LOG(...) log_message(__FILE__, __LINE__, __VA_ARGS__)
inline void log_message(const char* filename, int line, ...) {
// Logging code omitted for brevity.
}
#endif
// other stuff
#endif
Now, if your main.c file looks as follows:
#define NDEBUG
#include "header.h"
int main(void) {
// …
LOG("hello");
}
… then, after preprocessing, your main.c file would looks something like this (I’m omitting some irrelevant stuff):
# 1 "main.c"
# 1 "./header.h" 1
# 13 "./header.h"
// other stuff
# 3 "main.c" 2
int main(void) {
// …
((void) 0);
}
… in other words, only the part of header.h that corresponds to #ifdef NDEBUG was included, not the part in the #else clause. If we had included header.h without defining NDEBUG, then the included header code would have contained the definition of log_message.
As others have said, #include will paste verbatim the entire file you are targeting. However you normally include headers, which tend to look like
extern int a (int b);
extern char * c (void);
static inline int d (int e, int f) {
...
}
extern void * g (void * h);
...
The code above occupies exactly zero memory (unless you start using one of the inline functions), since it is entirely composed of instructions for the compiler and nothing else.
Let's say I have a header file "header.h" with a function definition.
#ifndef HEADER_FILE
#define HEADER_FILE
int two(void){
return 2;
}
#endif
This header file has an include guard. However, I'm kind of confused as to what #define HEADER_FILE is actually doing. Let's say I were to forget the include guard, it would have been perfectly legal for me to completely ignore adding '#define HEADER_FILE'.
What exactly are we doing when we define HEADER_FILE? What are we defining? And why is it okay to forget the include guard in which case we can also forgot adding #define HEADER_FILE?
It's a preprocessor macro.
All of it is preprocessor syntax, that basically says, if this macro has not already been defined, define it and include all code between the #ifndef and #endif
What it accomplishes is preventing the inclusion of file more than once, which can lead to problems in your code.
Your question:
And why is it okay to forget the include guard in which case we can also forgot adding #define HEADER_FILE?
It's OK to forget it because it's still legal C code without it. The preprocessor processes your file before it's compiled and includes the specified code in your final program if there's no logic specifying why it shouldn't. It's simply a common practice, but it's not required.
A simple example might help illustrate how this works:
Your header file, header_file.h we'll say, contains this:
#ifndef HEADER_FILE
#define HEADER_FILE
int two(void){
return 2;
}
#endif
In another file (foo.c), you might have:
#include "header_file.h"
void foo() {
int value = two();
printf("foo value=%d\n", value);
}
What this will translate to once it's "preprocessed" and ready for compilation is this:
int two(void){
return 2;
}
void foo() {
int value = two();
printf("foo value=%d\n", value);
}
All the include guard is accomplishing here is determining whether or not the header contents between the #ifndef ... and #endif should be pasted in place of the original #include.
However, since that function is not declared extern or static, and is actually implemented in a header file, you'd have a problem if you tried to use it in another source file, since the function definition would not be included.
You prevent the file from being included more than once, here
#ifndef HEADER_FILE
you test if HEADER_FILE is NOT defined, in case that's true then
#define HEADER_FILE
would define it, now if you include the file in another file, the first time it will define HEADER_FILE, while the second time, it will be already defined and hence the content of the file is not included again, since the #ifndef HEADER_FILE will be false.
Remember that these are evaluated by the preprocessor before actual compilation is done, so they are evaluated at compile time.
First of all, in modern C++ compile you can use #pragma once instead of include guards.
Then, your example is a little confuse, because you define an extern function in your header. Normally include files are used to define function's declarations and not function's definitions.
If you define functions in your header and if this header is used by more than one CPP source files, this function will be define more times with same name and you will have an error when program will be linked !
A better include would be
#ifndef HEADER_FILE
#define HEADER_FILE
int two(void);
#endif
or
#ifndef HEADER_FILE
#define HEADER_FILE
static int two(void) { return 2; }
#endif
or
#pragma once
static int two(void) { return 2; }
In the last case, function two() is defined in each CPP source files that include this header; but this function is static, so CPP sources are compiled correctly and CPP program is linked without problem.
In your question, you ask
in which case we can also forgot adding #define HEADER_FILE?
Personally, I use same header in very special tricky situation.
The following 2 includes are a "good" example:
/*******************************************************************
* XTrace.Configuration.h
********************************************************************
*/
#pragma once
#define MODULEx(n) extern StructDefineMODULE MODULE_##n;
#include "XTrace.Modules.h"
#undef MODULEx
#define MODULEx(n) { #n, &MODULE_##n } ,
static struct ModuleTRACE tModuleTrace[]
= {
#include "XTrace.Modules.h"
{ 0, 0 }
};
where XTrace.Modules.h include is following
/*******************************************************************
* XTrace.Modules.h
********************************************************************
*/
MODULEx( BBDIXFILE )
MODULEx( CECHO )
MODULEx( INITDBFIELD )
MODULEx( IVIRLUX )
The first include contains #pragma once and call same internal include 2 times.
The first time it is called to define extern declaration of StructDefineMODULE structure.
The second time is is called to initialize an array of ModuleTRACE structures.
Since this include is called 2 times, #pragma once or #ifndef must be avoid.
In using an internal include I'm sure at 100% that all elements used to define StructDefineModule are also used to initialize tModuleTrace[] array.
The include internal result, would be
/*******************************************************************
* XTrace.Configuration.h
********************************************************************
*/
#pragma once
extern StructDefineMODULE MODULE_BBDIXFILE;
extern StructDefineMODULE MODULE_CECHO;
extern StructDefineMODULE MODULE_INITDBFIELD;
extern StructDefineMODULE MODULE_IVIRLUX;
static struct ModuleTRACE tModuleTrace[]
= { { "BBDIXFILE" , &MODULE_BBDIXFILE }
, { "CECHO" , &MODULE_CECHO }
, { "INITDBFIELD" , &MODULE_INITDBFIELD }
, { "IVIRLUX" , &MODULE_IVIRLUX }
, { 0, 0 }
};
I hope that this can help you to understand why, in some situations, include guards can be avoid !
I have been reading about C for a while now and decided lets write a little add program, nothing fancy at all. My understanding of C headers is that they are "interfaces" (such as like java and other languages) but where you can also define variable that either have set values or not..
So I wrote this:
#include <stdio.h>
#include <stdlib.h>
#include "sample.h"
int main(int argc, char** argv) {
printf("hello World\n");
add(12, 18);
return (EXIT_SUCCESS);
}
int add(int a, int b){
int value = a+b;
printf("value = %d\n", value);
return 0;
}
It has a header file that looks like such:
#ifndef SAMPLE_H_GUARD
#define SAMPLE_H_GUARD
int add(int a, int b);
#endif
I thought header files, and this is where I am lost on their definition, was suppose to define the use of add, so all I would have to do is call add - From my understanding, I define the rules of add and then implement the functionality of add....
Also, A lot of the material I have read shows one header file for multiple C files. where as a lot of projects today have one header per one c, meaning Sample.h belongs to Sample.c and nothing else.
Can some one shed some light on this?
Could I have done this like so:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "sample.h"
int main(int argc, char** argv) {
printf("hello World\n");
add(12, 18);
return (EXIT_SUCCESS);
}
add.c
#include <stdio.h>
#include <stdlib.h>
#include "sample.h"
int add(int a, int b){
int value = a+b;
printf("value = %d\n", value);
return 0;
}
sample.h
#ifndef SAMPLE_H_GUARD
#define SAMPLE_H_GUARD
int add(int a, int b);
#endif
I believe in the book I was reading: C Programming Language they had a calculator example split up like this, my question is how does C know where add is defined? It knows the rules for it based on the header file, i think, but not where the actual implementation is ....
There example where they split of the files like such doe not have something like #include "add.c" all they do is include the header file in the files that either implement or use this functionality.
Note: obviously the calculator example and my example are going to be different but fundamentally the same - for those who have the book. I am just lost on how to use header files effectively and efficiently.
A header file in C would declare the function add for those modules that need it, but not define the function. The function is still to be defined in its own module (e.g., in your case, add.c).
So in general, to make a function foo available to several modules, you would normally:
Choose a header file (maybe it's own if there are other associated
defines, etc) to declare foo. For example, perhaps foo.h would
have void foo(...);
In some module, perhaps foo.c, you would define the complete
function foo.
In any module that wants to call foo, you would #include "foo.h"
(or whatever header you used) and call the function.
When you compile/link the code, you would make sure all modules,
including foo.o or whatever module has foo defined in it, were
present.
A declaration, given in the header file, provides (of course) the function name, the function return type as well as listing all the parameters and their types. This is all the compiler needs to know to figure out how to call the function from the calling module. At link time, addresses are all resolved so that the modules then know exactly where the function is in its own particular module.
My understanding of C headers is that they are "interfaces" (such as
like java and other languages) but where you can also define variable
that either have set values or not..
This is not correct. You cannot "define" variables - well, you can but that will cause multiple definitions error while compiling code if you include header more than once.
Could I have done this like so:
Regarding your code - both variants are correct. C language uses headers to read declarations and hence headers are optional as well. You can have your code split into as many as you want .h and .c files. Compiler will create an object file for each .c file. All .h files included in a c file are basically embedded in that C file "before compilation" i.e. in preprocessing phase. Linker then comes in picture which combines objects to produce the executable.
Please don't hesitate if something is not clear in my answer.
I am restricted by very specific (and rather senseless...) filing system and I can't create header files or split existing files into files holding only functions and only execution calls. I can only create .c files that can be executed and have some sort of output.
A lot of code can be reused but I am being forced to copy some functions from file to file.
Is it possible to cure this mess by including but not compiling one or more file or omitting some functions in the included files? Maybe adding some debugging into the mix can allow to compile only part of included files?
Put the shared code like this, so that it can compile on it's own and at the same time you can include it from other .c files without getting duplicate main functions:
// shared.c
#ifndef SHARED_C
#define SHARED_C
#if __INCLUDE_LEVEL__ == 0
# include <stdio.h>
# include <stdlib.h>
int main() {
fprintf(stderr, "shared file, not to run!\n");
return EXIT_FAILURE;
}
#endif
int shared_func() { return 1; }
#endif
And use it from other files
#include "shared.c"
int x = shared_func();
Can you use the pre-processor? Something like:
// this is file1.c
int Foo(int bar);
#ifndef HEADERS
int Foo(int bar)
{
return 42;
}
#endif
and
// this is file2.c
#define HEADERS
#include "file1.c"
Foo(42);