I have a structure defined in a header file called data.h.
I am including data.h in myfile.c.
In the structure, I have part of the variables blocked off with:
#ifndef TEST
int x;
#endif
and in myfile.c I have:
#ifdef TEST
localx++;
#else
mystruct.x++; //<-compiler complains on this line when compiling
#endif
When I try to compile with -DTEST I get a compiler complaining that mystruct type does not containing a field called x. What is up with this?
I don't have a C compiler handy, so here is what I just typed up:
in data.h
typdef struct {
#ifndef TEST
int x;
#endif
int y;
} coords;
in myfile.c
#include "data.h"
static coords coord1;
int localx;
int main( )
{
#ifdef TEST
localx = 1;
#else
coord1.x = 1;
#endif
coord1.y = 2;
printf("%i\n", coord1.x);
printf("%i\n", coord1.y);
printf("%i\n", localx);
return 0;
}
This compiles when I type cc myfile.c but not with cc myfile.c -DTEST
I am using the MIPSPro C compiler referenced here.
You most recent edit (which may well be different by the time anyone reads this) will have a problem in the section that has a bunch of printf() statements. The line:
printf("%i\n", coord1.x);
is referencing the x member of the struct regardless of the setting of the TEST preprocessor macro. It needs to be inside a conditional compilation section too in order to compile correctly (rather not compile at all) when the x member doesn't exist.
Since you are using ifndef for the field x, it is only there to use if TEST is not defined!!
#ifdef allows a section of a program to be compiled only if the macro that is specified as the parameter has been defined, no matter which its value is. For example:
#ifdef TABLE_SIZE
int table[TABLE_SIZE];
#endif
In this case, the line of code int table[TABLE_SIZE]; is only compiled if TABLE_SIZE was previously defined with #define, independently of its value. If it was not defined, that line will not be included in the program compilation.
#ifndef serves for the exact opposite: the code between #ifndef and #endif directives is only compiled if the specified identifier has not been previously defined. For example:
#ifndef TABLE_SIZE
#define TABLE_SIZE 100
#endif
int table[TABLE_SIZE];
In this case, if when arriving at this piece of code, the TABLE_SIZE macro has not been defined yet, it would be defined to a value of 100. If it already existed it would keep its previous value since the #define directive would not be executed.
From: http://www.cplusplus.com/doc/tutorial/preprocessor/
Except for the typo (typdef), your example compiles fine for me using gcc.
Edit:
The new example shouldn't compile. You need to wrap every reference to "x" in #ifdef directives.
Also, gcc accepts the -D flag before the file list, but I don't have access to MIPSpro. The docs say you have the command line out of order.
Related
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?
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;
}
Following program compiles successfully and print 1000 without even calling a foo() function from our main() function. How is it possible?
#include<stdio.h>
void foo()
{
#define ans 1000
}
int main() {
printf("%d", ans);
return 0;
}
#defineis run by the preprocessor which is staged before the compiler. After the preprocessor is done, the code will look like this:
/* Everything that is inside stdio.h is inserted here */
void foo()
{
}
int main() {
printf("%d", 1000);
return 0;
}
And this is what actually get compiled.
The preprocessor is very important to make header files work. In them, you see this structure:
#ifndef foo
#define foo
/* The content of the header file */
#endif
Without this, the compiler would complain if a header file is included more than once. You may ask why you would want to include a header file more than once. Well, header files can include other header files. Consider this macro, which is useful for debugging. It prints the name of the variable and then the value. Note that you would have to do a separate version for different types.
#define dbg_print_int(x) fprintf(stderr, "%s = %d", #x, x)
This is pretty versatile, so you may want to include it in a header file for own use. Since it requires stdio.h, we include it.
/* debug.h */
#include <stdio.h>
#define dbg_print_int(x) fprintf(stderr, "%s = %d", #x, x)
What happens when you include this file and also include stdio.h in you main program? Well, stdio.h will be included twice. That's why debug.h should look like this:
/* debug.h */
#ifndef DEBUG_H
#define DEBUG_H
#include <stdio.h>
#define dbg_print_int(x) fprintf(stderr, "%s = %d", #x, x)
#endif
The file stdio.h has the same construct. The main thing here is that this is run before the compiler. The define is a simple replacement command. It does not know anything about scope or types. However, as you can see here, there is some basic logic built into it. Another thing that the preprocessor does is to remove all the comments.
You can read more about the C preprocessor here: http://www.tutorialspoint.com/cprogramming/c_preprocessors.htm
The #define is processed by the preprocessor before the compiler does anything. It is a simple text replacement. The preprocessor doesn't even know if the line of code is inside or outside a function, class or whatever [Ref: https://stackoverflow.com/a/36968600/5505997]. Clearly you do not need to call the function to set the value and obviously you will not get any error during compile.
As others have stated, #define is a preprocessor directive, not C source code. See Wiki here.
Point being, in your code #define ans 1000 is not a variable definition, meaning that even if you were calling foo() in the main, you would still not be setting "ans" at runtime, because it is simply not a variable. It is just telling the preprocessor what to do with the "label" "ans", when it finds it in your source code.
In this example, the main() will essentially be calling an empty foo() function:
int main()
{
foo(); // Calls an empty function
printf("%d", ans); // ans will have been substituted by 1000 by the time you start executing you code
return 0;
}
The definition of "ans" will simpy not exist anymore by the time you start executing you main(). This is what the preprocessor does (in part). It finds all the #defines declared in your entire source code and tries to find places in your code where you have used these defines. If you have not used them, it moves on (don't care), if you have, it substitutes the label by the actual defined value.
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'm trying to enable debugging options in MuPDF. For some reason they have used #ifndef NDEBUG and #endif greying out code I want to use. I searched throughout the library but couldn't find any traces of NDEBUG defined anywhere. I've managed to work around this by adding #undef NDEBUG in a header, but I would like to know if there is a more non-intrusive method to do so.
SO, can you enable "#ifndef/#endif" blocks from the makefile?
Also, why would you use #ifndef to grey out code? Isn't it supposed to be #ifdef NDEBUG?
You can add -DNDEBUG to the following 3 variables - CFLAGS, CPPFLAGS and CXXFLAGS in your Makefile to define NDEBUG.
Which is equivalent to adding #define NDEBUG
There are other variations too:
-DNBDEBUG=1
is equivalent to
#define NDEBUG 1
And to answer the question of why would someone use #ifndef instead of #ifdef is because it highlights your modifications to the original code much clearly.
For example consider the following code as the original version:
int a = 123;
int b = 346;
int c = a + b;
And you need to add a macro DO_MULT which will multiply instead - there are 2 ways to do this.
First Variation:
int a = 123;
int b = 346;
#ifdef DO_MULT
int c = a *b;
#else
int c = a + b;
#endif
Second variation:
int a = 123;
int b = 346;
#ifndef DO_MULT
int c = a + b;
#else
int c = a *b;
#endif
If you use difftools to see the changes - the second variation will show the diff more clearly compared to the first one.
One more reason why you would use a #ifndef is to DO something in CATCH-ALL-EXCEPT scenarios.
#ifndef won't omit the code if the flag is defined, hence it's usage. You've managed to include the code using #undef.
Both #ifdef and #ifndef are useful, as justification consider this contrived example: you have a bunch of debug printf code that you only want to compile into a Debug build, using #ifdef DEBUG conditions. In the same executable you also have code that you want to leave out of a Debug build. In this case using #ifndef DEBUG is your only choice.
You can define such flags in the makefile, and you can also try to remove previous definitions by using -U. Look for a CFLAGS variable in the makefile and add -UNDEBUG, or add it directly to the compiler call in the compilation target.
If the flag is being defined somewhere in the source tree then this won't help.