How to define a define in C? - c

Is it possible to write a #define that defines a #define?
For example:
#define FID_STRS(x) #x
#define FID_STRE(x) FID_STRS(x)
#define FID_DECL(n, v) static int FIDN_##n = v;static const char *FIDS_##n = FID_STRE(v)
But instead:
#define FID_DECL2(n, v) #define FIDN_##n v \
FIDS_##n FID_STRE(v)
FID_DECL works fine but creates two static variables. Is it possible to make FID_DECL2 work and having define two defines?

No; preprocessing is performed in a single pass. If you want or need more advanced behavior, consider using another tool to preprocess the source, like m4.
Further, the # in the replacement list (at the beginning of #define FIDN... would be parsed as the # (stringize) operator: the operand of this operator must be a named macro parameter, which define is not.

No while defining macros u should take care of one thing
that macro should not call itself (reccursively) either directly
or indirectly.
I know two static variables consuming 8 bytes will be expansive for u.
I have solution over it
#define FID_STRS2(x) #x
#define FID_STRE(x) FID_STRS2(x)
#define FID_DECL(n, v) static int FIDN_##n = v;static const char *FIDS_##n = FID_STRE(v)
Just rename them going reccursive

Related

C macro expansion including compiler switches

My current implementation defines a couple of variables depending on corresponding compiler switches:
#ifdef ENABLE_var1
int var1;
#endif
#ifdef ENABLE_var2
int var2;
#endif
The compiler switches will be set by -D option during make. The names will always consist of the same prefix and the variable name. Since it is always the same strategy, my idea is to replace this using a macro like:
DECLARE(var1)
DECLARE(var2)
Calling make -DENABLE_var1 should result in:
int var1;
Calling make -DENABLE_var1 -DENABLE_var2 should result in:
int var1;
int var2;
Since it is not possible to use #ifdef within a macro, is there a trick to achieve this?
As long as the variable names to be defined, potentially, are known, then this can be accomplished:
// Define a DEFINE_x macro for each x that might be enabled.
#if defined ENABLE_var1
#define DEFINE_var1 int var1;
#else
#define DEFINE_var1
#endif
#if defined ENABLE_var2
#define DEFINE_var2 int var2;
#else
#define DEFINE_var2
#endif
// Define DECLARE(x) to expand to the corresponding DEFINE_x macro.
#define DECLARE(x) DEFINE_##x
// List potential definitions.
DECLARE(var1)
DECLARE(var2)
If the names are not known, then this kludge works:
#define Comma() ,
#define Argument3c(a, b, c,...) c
#define Argument3b(a, b,...) Argument3c(a, b, __VA_ARGS__)
#define Argument3a(a,...) Argument3b(a, __VA_ARGS__)
#define Nullify1
#define NullifyHelper(x) Nullify##x
#define Nullify(x) NullifyHelper(x)
#define DECLARE(x) Argument3a(Comma Nullify(ENABLE_##x) (), int x;,,)
DECLARE(var1)
DECLARE(var2)
Understanding this requires following the preprocessing in great detail, but I will provide a few notes:
For -Dname, GCC defines name to be replaced by 1. The Nullify macro, with its helpers, causes ENABLE_x to be replaced by an empty sequence if ENABLE_x is defined to be 1 and by a non-empty sequence otherwise.
Then, if an empty sequence has resulted, we have Comma (), which expands to a comma. If it is not an empty sequence, we have Comma something (), which does not allow the function-like macro to be expanded, so some sequence not including a comma results.
Through the remaining macro expansions, this comma or lack thereof determines which argument is where in the argument list, allowing us to pick out either the desired definition or an empty sequence.
I advise against using this in production code. There is likely a better way to accomplish your configuration goal.

Converting macros to enum types in C

I am little bit confused. In our production environment, there are few macros already defined. These macros used to return some value. Now our requirement is to prepare some lookup based on these Macros' value. I have created char* array and defined some string at appropriate index. But my manger asked me to convert these macros to enum types and then do lookup. How to implement this using enum? What is the advantage of that? These macros are being used in many different files. Do I have to change anything if I defined enum type?
Thanks in advance !
Sample code:
#define macro_1 1
#define macro_2 2
#define macro_3 3
#define macro_4 4
Lookup:
const char* lookup[] = {.....};
How to implement this using enum?
I suppose your manager asked you to map the macros to enum type. You can simply define an enum type, as long the macros all have integer value, and the enum values don't use the same names as macros.
What is the advantage of that?
Macros are generally not encouraged as they are replaced by value before entering the compiler, it can be error prone compared to using enum types that are checked and managed by compiler.
These macros are being used in many different files. Do I have to change anything if I defined enum type?
Unfortunately yes. But if your macros are isolated in a centeral header file, you can work around by renaming the macros and naming the original names to enum value.
You may find this article useful. http://www.cs.utah.edu/~germain/PPS/Topics/C_Language/enumerated_types.html
Some codes
#include <stdio.h>
#define old_macro_1 1
#define old_macro_2 2
#define old_macro_3 3
enum MacroValues {
macro_1 = old_macro_1,
macro_2 = old_macro_2,
macro_3 = old_macro_3
};
void test_macros(void)
{
const char* lookup[] = {"M0", "M1", "M2", "M3"};
// use an enum variable directly
printf("enum MacrosValues %d\n", macro_1);
// define an enum variable to use as index
enum MacroValues m1 = macro_2;
printf("lookup[%d] = %s\n", m1, lookup[m1]);
}
int main(void)
{
test_macros();
return 0;
}

Distinguish variable and constant in #define macro

I have macros like this:
#define _DDR_0 DDRD
#define _DDR_1 DDRD
#define _DDR_2 DDRD
// ....
#define _PN_0 0
#define _PN_1 1
#define _PN_2 2
// ...
/** Configure pin as output */
#define as_output(pin) sbi(_DDR_##pin, _PN_##pin)
void as_output_n(const uint8_t pin);
It is used like so:
as_output(2);
uint8_t b = 1;
as_output_n(b);
The _n variant is used for variables, the macro for constants (because it's much faster to do this with a macro).
Is there any possible way to make it so you can use as_output always, and depending on it being constant OR a variable, use the macro OR the function?
Macros are expanded by the preprocessor which has no knowledge of what the code does. From the preprocessor's point of view all the macro arguments are simply tokens (with no logical meaning). In this case as_output macro is used to manufacture new code (via token pasting).
So, what you're trying to do, is not possible using just macros (there could be a way if b would be a macro itself, but i guess that's not what you're looking for).
You could use a const array for your _DDR* and PN* values, and an inline function instead of macros.

What is the difference between global variables and #define in c

Whats the reason why there are 2 opportunities :
global variables
symbolic constants with #define ?
So I know what #define does but I don't know what the difference in use is.
Which situation do I must have thus I'm able to decide myself upon the right opportunitie? What is one of the opportunities able to do what the other one doesn't ? I hope that I could clarify what I mean.
Well, global variables can be edited from everywhere.
Basically, in the low level, a variable is stored in RAM memory and created after launching your application, it always has an address in RAM. Defines are just macros, your compiler will just replace your define names with its values in the compilation step.
#define can't be edited, it's just a macros. And #define is not just about values, you can define almost everything that you want, for example:
// Defining a constant
#define PI 3.14
// Defining an expression
#define MIN(x,y) ((x)<(y))?(x):(y)
// Defining a piece of code
#define STOP_TIMER \
clock_gettime(CLOCK_REALTIME, &__t1); \
__lasttime = \
(double) (__t1.tv_sec - __t0.tv_sec) + \
(double) (__t1.tv_nsec - __t0.tv_nsec) / 1000000000.0;
And, in most situations, defines are used to set some OS-specific or hardware-specific values. It's a really powerful thing, because it gives you the opportunity to change things dynamically in the compilation step. For example:
// Example with OS
#ifdef __linux__
#define WELCOME_STRING "welcome to Linux!"
#else
#define WELCOME_STRING "welcome to Windows!"
#endif
// Example with hardware
#if __x86_64__ || __ppc64__
#define USING_64BIT
#else
#define USING_NOT64BIT
#endif
Consider this small example
#define num 5
int number = 5;
num is a macro and number is a global variable.
One important difference is that num is not stored in the memory, num is just the substitute for 5, but number uses memory.
Also, macro's are preprocessor directives, their values cannot be changed like variables.
So, no doing
num = 6;
later in the code. You will have to use #undef to undefine it and define it again to change the value.
Global variables can be accessed and edited from everywhere. #define constants can't be edited, just read.
Examples:
We use #define ERROR 666 to define a programmer pre compile time constant for an error for the whole program.
We use a global variable for a count of how many operations a function did and this value can be read by other functions as well.
There's no point to make the error as a global variable since it shouldn't be edited and you can't use the #define x as a counter.
#define is declared on top of the code, it means before the declaration of the class. And it serves as to define (as the name says) a constant, that can be read but not changed.
A global variable can be accessed globally on the code, and at same time changed.

Symbolic constants in C (#define statement)

After reading through some of K&R's The C Programming Language I came across the #define symbolic constants. I decided to define...
#define INTEGER_EXAMPLE 2
#define CHAR_EXAMPLE 2
...so my question is how does C know if I'm defining an int or a char type?
#define-d names have no types. They just define textual replacements.
What the compiler is seeing is the preprocessed form. If using GCC, try gcc -C -E somesource.c and have a look at the (preprocessed) output.
In the 1980s the preprocessor was a separate program.
Read about the cpp preprocessor, and preprocessor and C preprocessor wikipages.
You could even define ill-defined names like
#define BAD #*?$ some crap $?
And even more scary you can define things which are syntactically incomplete like
#define BADTASTE 2 +
and later code BADTASTE 3
Actually, you want to use parenthesis when defining macros. If you have
#define BADPROD(x,y) x*y
then BADPROD(2+3,4+5) is expanded to 2+3*4+5 which the compiler understands like 2+ (3*4) +5; you really want
#define BETTERPROD(x,y) ((x)*(y))
So that BETTERPROD(2+3,4+5) is expanded to ((2+3)*(4+5))
Avoid side-effects in macro arguments, e.g. BETTERPROD(j++,j--)
In general, use macros with care and have them stay simple.
Regarding these defines, it doesn't, the expanded macros doesn't have a type. The pre-processor which processes the #define is just replacing text within the source code
When you use these defines somewhere, e.g.
int i = INTEGER_EXAMPLE;
This will expand to
int i = 2;
Here the literal 2 (which in this context is an int) is assigned to an int.
You could also do:
char c = INTEGER_EXAMPLE;
Here too, the literal 2 is an int, and it is assigned to a char. 2 is within the limits of a char though, so all is ok.
You could even do:
int INTEGER_EXAMPLE = 2;
This would expand to
int 2 = 2;
Which isn't valid C.
#define STRING VALUE
is just an instruction for the pre-processor to replace the STRING with VALUE
afterwards the compiler will take control and will check the types
It doesn't, this is the preprocessor. The type of the constant is dependent on the context in which it is used. For instance:
#define INT_EXAMPLE 257
char foo = INT_EXAMPLE;
will attempt to assign 257 in a char context which should generate a warning unless char has more than 8 bits on your computer.
#Defines are nothing but literal replacements of values. You might want to use
static const
As it respects scope and is type-safe. Try this:
#define main no_main
int main() // gets replaced as no_main by preprocessor
{
return 0;
}
Should give you linking errors. Or you could try and fool your teacher by this
#define I_Have_No_Main_Function main //--> Put this in header file 1.h
#include"1.h"
int I_Have_No_Main_Function()
{
return 0;
}
It doesn't. The #define statements are processed before the compiler starts its work. Basically the pre-processor does a search and replace for what you wrote and replaces it, for instance, all instances of INTEGER_EXAMPLE are replaced with the string 2.
It is up to the compiler to decide the type of that 2 based on where it's used:
int x = INTEGER_EXAMPLE; // 2 is an integer
char y = INTEGER_EXAMPLE; // 2 is a char
Preprocessor cannot know the type of the macro definition. Preprocessor will just replace all occurrence of 'CHAR_EXAMPLE' with '2'. I would use cast:
#define CHAR_EXAMPLE ((char)2)

Resources