0

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));
}
orORorOR
  • 143
  • 9
  • "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" What makes you think so? Please describe your debugging methods and results. – Yunnosch Jul 24 '20 at 12:34
  • "Is there some way to get this to work without having to stuff all of the .c code inside the .h file?" Without more info the answer is "Yes." Would you like to provide a [mre]? – Yunnosch Jul 24 '20 at 12:34
  • unless I define the macro inside of the .h file, the debug functions remain greyed out, but i can still write a call to them since the prototype (e.g. int func(int a, int b) is still visible, but the definitions are greyed out. i will update my OP – orORorOR Jul 24 '20 at 12:35
  • "grayed out"? What magic juju are you using to view this? Perhaps your visualization software is not in sync with your compiler. More context is needed. – William Pursell Jul 24 '20 at 13:33
  • Not relevant to your root problem, but do not define identifiers beginning with an underscore followed by and upper case letter (or another underscore). Those identifiers are reserved. – M. Nejat Aydin Jul 24 '20 at 13:36
  • 1
    I'm using Visual Studio (Windows) to code in C, it greys out code within the `#ifdef` because the macro is not seen as defined from within my test.c file as I want to define it in the main.c file – orORorOR Jul 24 '20 at 13:56
  • I edited my answer to show you how to `#include` one `.c` into another, and hopefully satisfy a variation of what you are looking for. I also explain (via a link) the limitations of this approach. One being you cannot practically `#include` a `.c` file that contains the `main()` function into another `.c` file as it will cause a `multiply defined symbol error` for the `main()` funciton. – ryyker Jul 24 '20 at 14:57

3 Answers3

1

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
ryyker
  • 22,849
  • 3
  • 43
  • 87
0___________
  • 60,014
  • 4
  • 34
  • 74
  • 1
    Too much guessing for my taste. And seeing that OP said "I define the macro before including anything", I am not convinced that you even guessed plausibly.... – Yunnosch Jul 24 '20 at 12:36
  • this does indeed work and I do not deny it, but I wish to declare it inside the main file instead of inside each header file since it is used across a large number of files (enables debugging functions) and i do not wish to have to define it in each header when i need it – orORorOR Jul 24 '20 at 12:39
  • so have your debug functions in the separate .c & .h pair. – 0___________ Jul 24 '20 at 12:44
  • Yeah, prototype is in .h and definition is in .c – orORorOR Jul 24 '20 at 12:48
0

"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;
}        
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • This works and It is how my code currently works, but I wish to be able to define the macro in my main file and have it be visible from the .c file too, somehow, as there's lots and lots of files that use it (to enable debugging functions) and I would need to define it and undefine it in too many files manually – orORorOR Jul 24 '20 at 13:55
  • @orORorOR - The only way to do this is to `#include` one `.c` file into another `.c` file. This can be done. However ***you cannot*** `#include` the `main.c` into another `.c` file, it has to be the other way around, otherwise you will get a _multiply define symbol_ error for `main(...)`. So, you could create a .c file that contains everything, then #include it into the `main.c` file. Will that work for you? – ryyker Jul 24 '20 at 14:11
0

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.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157