Possible to #if or #ifdef based on preprocessor-generated "thing" - c

I'm trying to engage in some C-preprocessor-only templating efforts in order to type-specialize some code. I've tried to boil it down a bit, so this example seems trivial and pointless, but the real challenge is getting the "include" blocking.
Say I have a "template" file, that gets #included from other source files that define T_ELEMENT_TYPE before including the template.
// Template file...
#ifndef T_ELEMENT_TYPE
#error #define T_ELEMENT_TYPE
#endif
#define PASTER(x,y) x ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define SYMBOLNAME EVALUATOR(SymbolFor, T_ELEMENT_TYPE)
#ifndef SYMBOLNAMEISDEFINED
#define SYMBOLNAMEISDEFINED EVALUTOR(DEFINEDFOR, T_ELEMENT_TYPE)
int SYMBOLNAME(T_ELEMENT_TYPE arg)
{
// do something with arg
return 0;
}
#endif // Guard #ifdef
Then I want to include that template from multiple instantiation sites, but I only want the templated function to be generated ONCE per unique T_ELEMENT_TYPE (so as not to create duplicate symbols.) Like, say this:
// Template-using file...
#define T_ELEMENT_TYPE int
#include "Template.c"
#undef T_ELEMENT_TYPE
#define T_ELEMENT_TYPE float
#include "Template.c"
#undef T_ELEMENT_TYPE
#define T_ELEMENT_TYPE int
#include "Template.c"
#undef T_ELEMENT_TYPE
int someOtherFunc()
{
int foo = 42;
foo = SymbolForint(foo);
float bar = 42.0;
bar = SymbolForfloat(bar);
return foo;
}
So I'm looking for something I can use in the template code. I imagined it might look something like this (although this does not work):
// Template file...
#ifndef T_ELEMENT_TYPE
#error #define T_ELEMENT_TYPE
#endif
#define PASTER(x,y) x ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define SYMBOLNAME EVALUATOR(SymbolFor, T_ELEMENT_TYPE)
#ifndef SYMBOLNAMEISDEFINED
#define SYMBOLNAMEISDEFINED EVALUTOR(DEFINEDFOR, T_ELEMENT_TYPE)
int SYMBOLNAME(T_ELEMENT_TYPE arg)
{
// do something with arg
return 0;
}
#endif // Guard #ifdef
This particular incantation blocks ALL multiple instantiations of the template, not just for different values of T_ELEMENT_TYPE.
Is there a trick I can use to get this effect? Or am I just off the C-Preprocessor reservation, so to speak?

I think you're off the reservation. The first "argument" to #define, the macro name, isn't subject to macro-expansion. So I don't think the preprocessor can define a different symbol according to the value of T_ELEMENT_TYPE. Neither can the preprocessor construct a "list" of already-seen types and check for existence in that.
So I think the include-guard will have to be outside the file:
#ifndef included_mytemplatefile_h_int
#undef T_ELEMENT_TYPE
#define T_ELEMENT_TYPE int
#include "mytemplatefile.h"
#define included_mytemplatefile_h_int
#endif
Alternatively, if your template file header only declares the function SymbolFor_int, instead of defining it, then multiple inclusion isn't harmful. You could have a normal include guard around the parts of the file that don't depend on the current value of T_ELEMENT_TYPE, including the definitions of PASTER, EVALUATOR, SYMBOLNAME. You'd need a separate template file containing definitions, which the program (rather than each translation unit) needs to have exactly once:
template_%.c :
echo "#define T_ELEMENT_TYPE $*" > $#
echo "#include \"mytemplatedefinitions.c\"" >> $#
Then add template_int.o to the list of files linked into your program.

Related

Conditional macro definition to emulate default define

I'm working on some geometry-based code. The task at hand involves use of a bounding-box to contain the solid specimen. Now, in the code I have devised two different types of such boxes, namely INNER_BOUNDING_BOX and OUTER_BOUNDING_BOX. The code further expects use of any one of the two boxes, but not both. I'm trying to achieve it through the use of preprocessor.
I have written further code based on a couple of macros namely USE_INNER_BOUNDING_BOX and USE_OUTER_BOUNDING_BOX. I can ensure that at any time any one macro is defined through some simple construct like this:
#if defined(USE_INNER_BOUNDING_BOX) && defined(USE_OUTER_BOUNDING_BOX)
#undef USE_INNER_BOUNDING_BOX
#undef USE_OUTER_BOUNDING_BOX
#define USE_INNER_BOUNDING_BOX
#endif
#ifndef USE_INNER_BOUNDING_BOX
#ifndef USE_OUTER_BOUNDING_BOX
#define USE_INNER_BOUNDING_BOX
#endif
#endif
Now, if I wanted to use any particular box, I could just define the corresponding macro. The difficulty comes with wanting for use of a default setting macro say USE_DEFAULT_BOUNDING_BOX, which I could use to then set up define for any one of USE_INNER_BOUNDING_BOX or USE_OUTER_BOUNDING_BOX when both or none of them are explicitly defined.
I'd be inclined towards portable code, but compiler-specific trick could also pass. I'm using Visual Studio 2012.
Reliable one-of-many selections like those can better be done by selecting them with a single multi-value switch right away.
#define BOUNDING_INNER 1
#define BOUNDING_OUTER 2
/* default */
#define BOUNDING_BOX_TO_USE BOUNDING_INNER
/* alternatively please activate below line
#define BOUNDING_BOX_TO_USE BOUNDING_OUTER
*/
If you need to stay backward compatible to some configurations,
e.g. your code has already been used by others,
you can derive the single switch from the two, matching your default behaviour.
The advantage is to avoid #undef (in case you agree that it is an advantage to do so).
#if defined(USE_INNER_BOUNDING_BOX) && defined(USE_OUTER_BOUNDING_BOX)
#define BOUNDING_BOX_TO_USE BOUNDING_INNER
#endif
#ifndef USE_INNER_BOUNDING_BOX
#ifndef USE_OUTER_BOUNDING_BOX
#define BOUNDING_BOX_TO_USE BOUNDING_INNER
#endif
#endif
/* In case you are as paranoid a programmer as I am,
you might want to do some plausibility checking
here. ifndef, >0, <2 etc., triggering some #errors. */
/* Later, in code doing the actual implementation: */
#if (BOUNDING_BOX_TO_USE == BOUNDING_INNER)
/* do inner bounding stuff */
#endif
/* other code, e.g. common for inner and outer */
#if (BOUNDING_BOX_TO_USE == BOUNDING_OUTER)
/* do outer bounding stuff */
#endif
Since there are only two values I would use only one boolean variable:
#ifndef USE_OUTER_BOUNDING_BOX
#define USE_OUTER_BOUNDING_BOX 0
#endif
If USE_OUTER_BOUNDING_BOX is zero (false) the inner bounding box is used.
test.c:
#include <stdio.h>
#ifndef USE_OUTER_BOUNDING_BOX
#define USE_OUTER_BOUNDING_BOX 0
#endif
int main(void)
{
printf("%d\n", USE_OUTER_BOUNDING_BOX);
return 0;
}
Example:
$ cc -o test -DUSE_OUTER_BOUNDING_BOX=0 test.c
$ ./test
0
$ cc -o test -DUSE_OUTER_BOUNDING_BOX=1 test.c
$ ./test
1
Here is what I ended with:
// Comment to use bigger outer Bounding-Box
#define USE_INNER_BOUNDING_BOX
#define INNER_BOUNDING_BOX 0
#define OUTER_BOUNDING_BOX 1
#define DEFAULT_BOUNDING_BOX OUTER_BOUNDING_BOX
#if defined(USE_INNER_BOUNDING_BOX) && !defined(USE_OUTER_BOUNDING_BOX)
#define USE_BOUNDING_BOX INNER_BOUNDING_BOX
#elif defined(USE_OUTER_BOUNDING_BOX)
#define USE_BOUNDING_BOX OUTER_BOUNDING_BOX
#else
#define USE_BOUNDING_BOX DEFAULT_BOUNDING_BOX
#endif
#if (USE_BOUNDING_BOX == INNER_BOUNDING_BOX)
#undef USE_OUTER_BOUNDING_BOX
#define USE_INNER_BOUNDING_BOX
#else
#undef USE_INNER_BOUNDING_BOX
#define USE_OUTER_BOUNDING_BOX
#endif
This just works in this case. In case of more boxes, I'd append the conditional blocks.

Does the use #ifndef and #define change the memory allocation?

I recently saw a header file with such defines:
#ifndef DEFINE_ME
#define DEFINE_ME 1
char abc[10];
#endif
but I also found that DEFINE_ME was never defined in any other header file of the project so why was #ifndef used? does it have to do any thing with memory?
It's called an include guard.
The purpose of DEFINE_ME is to prevent the particular (where it's defined) header file being included multiple times accidentally.
To understand how it works, try without include guard:
header.h:
int x = 5;
file.c:
#include "header.h"
#include "header.h"
int main() {
printf("%d\n", x);
}
and then try with an include guard:
header.h:
#ifndef DEFINE_ME
#define DEFINE_ME 1
int x = 5;
#endif
file.c:
#include "header.h"
#include "header.h"
int main() {
printf("%d\n", x);
}
When you have DEFINE_ME, the header will be included the first time in fil.c, the header.h is included as DEFINE_ME wasn't defined before. But the next #include "header.h" wouldn't include the contents of the guard as DEFINE_ME has already been defined by the previous inclusion.
It's include guard.
The purpose of This is to prevent multiple declaration of variable.
ifndef = if not defined.
then define it..
if defined then use the previous declaration ..
suppose u have two header files
header1:
#ifndef DEFINE_ME
#define DEFINE_ME 1
#endif
header 2:
#ifndef DEFINE_ME
#define DEFINE_ME 1
#endif
now if in c file header 2 is included first then it will include the value from header 2 not from header 1.. as it is already defined in header 2
You can have header file guard also as explained below:
Header1.h
#ifndef _header1
#define _header1
#ifndef VAR1
#ifdef VAR1 5
#endif
#endif
Header2.h
#ifndef _header2
#define _header2
#ifndef VAR1
#ifdef VAR1 5
#endif
#endif
Now you have used a guard so that u by mistake include same header in different files of same project then also u will be safe.

Is it possible create a "variable" header guard name in C?

fellow programmers,
I'm new to the C preprocessor and have been recently trying to create a generic-like library in C (as an exercise), and I've come upon a little problem when creating header guards.
All the preprocessor macros are set up so I can include and use my headers like this:
#define TYPE int
#include "myheader.h"
#undef TYPE
#define TYPE float
#include "myheader.h"
#undef TYPE
int main(void){
//Do stuff
MyFunc_int();
//More stuff
MyFunc_float();
return 0;
}
But the problem appears when I need to include the headers in more than one file. Header guards are usually applied in this case, but since the header can be included once -for each type-, neither the usual construction nor #pragma once can be used.
My question then is: Is it possible to create a "variable" header guard to work for different TYPE definitions?
When you want to include the header from various compilation units, you could divide the header into a publich part that plays the role of the header and a private part that plays the role of a *.c file, for example:
#define M_CONCAT(a, b) a##b
TYPE M_CONCAT(TYPE, _min)(TYPE a, TYPE b);
#ifdef IMPLEMENT
TYPE M_CONCAT(TYPE, _min)(TYPE a, TYPE b)
{
return (a < b) ? a : b;
}
#endif /* IMPLEMENT */
Then you can include this header from multiple files, but you have to make sure that only one file defines IMPLEMENT before including the header:
#define IMPLEMENT // only in one file
#define TYPE float
#include "myheader.h"
#undef TYPE
#define TYPE int
#include "myheader.h"
#undef TYPE
This file could be a separate compilation unit, myheader.c. You must take care to implement the function for all types, however. (But the linker will tell you, which types you've missed.)
I suggest:
Remove the #include guards in myheader.h.
Create different header files for each TYPE.
intheader.h:
#pragma once
#define TYPE int
#include "myheader.h"
#undef TYPE
floatheader.h:
#pragma once
#define TYPE float
#include "myheader.h"
#undef TYPE
And then use:
#include "intheader.h"
#include "floatheader.h"
int main(void){
//Do stuff
MyFunc_int();
//More stuff
MyFunc_float();
return 0;
}
I think you're looking for something like this:
#if !defined HEADERGUARD && defined (TYPE==int)
#define HEADERGUARD
<stuff>
#endif
You may want to have HEADERGUARD_int and HEADERGUARD_float, depending on what you're doing inside the *.h file. More conventionally, people will break it into two *.h files.

What does a #define directive without an argument do?

On Apple's opensource website, the entry for stdarg.h contains the following:
#ifndef _STDARG_H
#ifndef _ANSI_STDARG_H_
#ifndef __need___va_list
#define _STDARG_H
#define _ANSI_STDARG_H_
#endif /* not __need___va_list */
#undef __need___va_list
What do the #define statements do if there's nothing following their first argument?
There are sort of three possible "values" for an identifier in the preprocessor:
Undefined: we don't know about this name.
Defined, but empty: we know about this name, but it has no value.
Defined, with value: we know about this name, and it has a value.
The second, defined but empty, is often used for conditional compilation, where the test is simply for the definedness, but not the value, of an identifier:
#ifdef __cplusplus
// here we know we are C++, and we do not care about which version
#endif
#if __cplusplus >= 199711L
// here we know we have a specific version or later
#endif
#ifndef __cplusplus // or #if !defined(__cplusplus)
// here we know we are not C++
#endif
That's an example with a name that if it is defined will have a value. But there are others, like NDEBUG, which are usually defined with no value at all (-DNDEBUG on the compiler command line, usually).
They define a macro which expands to nothing. It's not very useful if you intended it to be used as a macro, but it's very useful when combined with #ifdef and friends—you can, for example, use it to create an include guard, so when you #include a file multiple times, the guarded contents are included only once.
You define something like:
#define _ANSI_STDARG_H_
so that, later you can check for:
#ifdef _ANSI_STDARG_H_

Using C, one code, multiple headers if/else?

I have one piece of code that I can use for the same function on different sets of data which are defined in different header files . These header files may have the same variable defined differently.
I can pass a parameter to the code when I call it to specify which dataset I want to perform the function on.
What I would like to do is pass this parameter to the code where if the parameter equals X then I use headerX, or if parameter equals Y I use headerY.
It is my understanding that header files must be included before MAIN. Is it possible to include the header file after MAIN so that I can write an if/else statement to determine which header file I am calling?
If I can't do that then please help me figure this out.
You could use #ifdef - blocks to determine which data set you'd want to use before compiling. But if you wanted a different data set, you would need to change (recompile) the executable by changing that define.
Otherwise you would need to compile in C++ as straight C does not support overloaded functions.
Simply put, you just can't. You may be able to include headers before hand based on a condition. Just use #if-def blocks at the top of the file.
But you can't include it like if else:
This is WRONG
if(x == 1)
#include "header1.h"
else
#include "header2.h"
But you can do this at the top of the file:
#if SYSTEM_1
#include "system_1.h"
#elif SYSTEM_2
#include "system_2.h"
#elif SYSTEM_3
#include "system_3.h"
#endif
Or you could just use C++ which does support overloaded functions.
You can do simple metaprogramming by using the macro preprocessing phase. Create a "interface_myFunc.h" with something like
#define FUNCNAME(T) myFunc_ ## T
void FUNCNAME(theType)(theType t);
Create a "implement_myFunc.h" file with something like
void FUNCNAME(theType)(theType t) {
// do something with t
}
and then include this file in another file "myFunc.h"
#define theType toto
#include "interface_myFunc.h"
#undef theType toto
#define theType tutu
#include "interface_myFunc.h"
#undef theType tutu
and similar for the definitions, "myFunc.c"
#define theType toto
#include "implement_myFunc.h"
#undef theType toto
#define theType tutu
#include "implement_myFunc.h"
#undef theType tutu
Modern C, C11, also has ways to create a common interface for all these functions that you create by so-called type generic macros:
#define myFunc(X) \
_Generic((X), \
toto: FUNCNAME(toto), \
tutu: FUNCNAME(tutu) \
)(X)

Resources