Is it possible to implement a macro conditional inside a macro function in C. Something like this:
#define fun(x)
#if x==0
fun1;
#else
fun2;
#endif
#define fun1 // do something here
#define fun2 // do something else here
In other words, preprocessor decides which macro to use based on an argument value.
fun(0) // fun1 is "preprocessed"
fun(1) // fun2 is "preprocessed"
I know that this example doesn't work, but I want to know is it possible to make it work somehow?
M.
You cannot use pre-processor conditionals inside a pre-processor directive. Background and workarounds you find for example here: How to use #if inside #define in the C preprocessor? and Is it possible for C preprocessor macros to contain preprocessor directives?
Still, you could do:
#include <stdio.h>
#define CONCAT(i) fun ## i() /* For docs on this see here:
https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html */
#define fun(i) CONCAT(i)
void fun1(void)
{
puts(__FUNCTION__);
}
void fun2(void)
{
puts(__FUNCTION__);
}
int main(void)
{
fun(1);
fun(2);
}
This would result in:
...
int main(void)
{
fun1();
fun2();
}
being passed to the compiler and print:
fun1
fun2
You could obfuscate your code even more by doing for example:
...
#define MYZERO 1
#define MYONE 2
int main(void)
{
fun(MYZERO);
fun(MYONE);
}
resulting in the same code being passed to the compiler.
Related
I am trying to make a macro that will be take a predefined prefix and concatenate it to the wanted function name in the argument of the macro, but I have been unsuccessful.
For example, while this is the wanted function signature:
void somePrefix__someFunc(int a)
However, when I run it and check the symbol table of the program I end up with the expansion of:
FUNC_PREFIXsomeFunc
What am I doing wrong and how can I do this correctly?
The code I was trying to run:
#include <iostream>
#define CONCAT(A, B) A##B
#define FUNC_PREFIX somePrefix__
#define FUNC_NAME(_func) CONCAT(FUNC_PREFIX, _func)
void FUNC_NAME(someFunc)(int a)
{
std::cout << a << std::endl;
}
int main()
{
FUNC_NAME(someFunc)(2);
return 0;
}
P.S: I tried using the macro without a CONCAT wrapper (directly trying to concat FUNC_PREFIX##_func), but it still did not work.
The ## is always applied before the macro "replacement list" is (re)scanned, so in case CONCAT is expanded before the other items, we won't get the desired result. Whenever we end up with a ## in the replacement list during macro replacement, it is then applied before any further replacement.
So you need an additional helper macro to expand the FUNC_PREFIX, so that it is expanded before CONCAT is:
#include <stdio.h>
#define CONCAT(A, B) A##B
#define CONCAT_EXPAND(A, B) CONCAT(A,B)
#define FUNC_PREFIX somePrefix_
#define FUNC_NAME(func) CONCAT_EXPAND(FUNC_PREFIX, func)
void FUNC_NAME(someFunc)(int a)
{
printf("%s: %d\n",__func__, a);
}
int main()
{
FUNC_NAME(someFunc)(2);
return 0;
}
Output:
somePrefix_someFunc: 2
I want to implement in C something similar to lambda functions from C++( using macros and function pointers)
I think the biggest problem that I am facing is to define a function inside another function, and this thing is not possible in C. I think a better idea is to treat the lambda function ( passed through a macro ) as a lexical block.
I started some code:
#define func_name(line) func##line
#define line __LINE__
#define lambda(body, ret_type, ...) ret_type func_name(line)(__VA_ARGS__) \
{ \
body; \
} \
//#include <stdio.h>
lambda( printf("Hello from Lambda\n") , void, int a, float b)
int main(void) {
//printf("Hello World\n");
return 0;
}
I used gcc compiler with "-E" option to see preprocessor output:
void funcline(int a, float b) { printf("Hello from Lambda\n"); }
int main(void) {
return 0;
}
It's possible, but the lambdas will have to be stateless (no captures). You can use preprocessor to move function definitions around, but there is no way to use local variables from one function in another, or to introduce some kind of state into a function.
Also it makes the code very hard to debug. Since all functions using those pseudo-lambdas have to be wrapped in a macro, all line breaks in them are removed during preprocessing. It becomes impossible to place a breakpoint inside of such a function, or to advance through it line by line.
Here is an example of the usage. The implementation is at the end of the answer. The explanation of the syntax is right after the example.
Run on gcc.godbolt.org
#include <stdio.h>
#include <stdlib.h>
ENABLE_LAMBDAS(
void example1()
{
int arr[] = {4,1,3,2,5};
FUNC(int)(compare)(const void *a, const void *b)
(
return *(int*)a - *(int*)b;
)
qsort(arr, 5, sizeof(int), compare);
for (int i = 0; i < 5; i++ )
printf("%d ", arr[i]);
putchar('\n');
}
void example2()
{
int arr[] = {4,1,3,2,5};
qsort L_(arr, 5, sizeof(int), LAMBDA(int)(const void *a, const void *b)
(
return *(int*)a - *(int*)b;
));
for (int i = 0; i < 5; i++ )
printf("%d ", arr[i]);
putchar('\n');
}
int main()
{
example1();
example2();
}
) // ENABLE_LAMBDAS
Notice the ENABLE_LAMBDAS macro wrapping the whole snippet.
This example uses two ways of defining functions/lambdas:
FUNC(return_type)(name)(params)(body) just defines a function. The function definition is moved to the beginning of ENABLE_LAMBDAS, so it can be used inside of other functions.
LAMBDA(return_type)(params)(body) defines a pseudo-lambda. A function definition for it is generated at the beginning of ENABLE_LAMBDAS, with an automatically chosen unique name. LAMBDA... expands to that name.
If FUNC or LAMBDA are used inside of parentheses, the parentheses must be preceeded by the L_ macro. This is a limitation of the preprocessor, unfortunately.
The generated functions are always static.
Implementation:
// Creates a lambda.
// Usage:
// LAMBDA(return_type)(params)(body)
// Example:
// ptr = LAMBDA(int)(int x, int y)(return x + y;);
#define LAMBDA LAM_LAMBDA
// Defines a function.
// Usage:
// FUNC(return_type)(name)(params)(body)
// Example:
// FUNC(int)(foo)(int x, int y)(return x + y;)
// some_func(foo);
#define FUNC LAM_FUNC
// Any time a `LAMBDA` or `FUNC` appears inside of parentheses,
// those parentheses must be preceeded by this macro.
// For example, this is wrong:
// foo(LAMBDA(int)()(return 42;));
// While this works:
// foo L_(LAMBDA(int)()(return 42;));
#define L_ LAM_NEST
// `LAMBDA` and `FUNC` only work inside `ENABLE_LAMBDAS(...)`.
// `ENABLE_LAMBDAS(...)` expands to `...`, preceeded by function definitions for all the lambdas.
#define ENABLE_LAMBDAS LAM_ENABLE_LAMBDAS
// Lambda names are composed of this prefix and a numeric ID.
#ifndef LAM_PREFIX
#define LAM_PREFIX LambdaFunc_
#endif
// Implementation details:
// Returns nothing.
#define LAM_NULL(...)
// Identity macro.
#define LAM_IDENTITY(...) __VA_ARGS__
// Concats two arguments.
#define LAM_CAT(x, y) LAM_CAT_(x, y)
#define LAM_CAT_(x, y) x##y
// Given `(x)y`, returns `x`.
#define LAM_PAR(...) LAM_PAR_ __VA_ARGS__ )
#define LAM_PAR_(...) __VA_ARGS__ LAM_NULL(
// Given `(x)y`, returns `y`.
#define LAM_NO_PAR(...) LAM_NULL __VA_ARGS__
// Expands `...` and concats it with `_END`.
#define LAM_END(...) LAM_END_(__VA_ARGS__)
#define LAM_END_(...) __VA_ARGS__##_END
// A generic macro to define functions and lambdas.
// Usage: `LAM_DEFINE(wrap, ret)(name)(params)(body)`.
// In the encloding code, expands to `wrap(name)`.
#define LAM_DEFINE(wrap, ...) )(l,wrap,(__VA_ARGS__),LAM_DEFINE_0
#define LAM_DEFINE_0(name) name,LAM_DEFINE_1
#define LAM_DEFINE_1(...) (__VA_ARGS__),LAM_DEFINE_2
#define LAM_DEFINE_2(...) __VA_ARGS__)(c,
// Creates a lambda.
// Usage: `LAM_LAMBDA(ret)(params)(body)`.
#define LAM_LAMBDA(...) LAM_DEFINE(LAM_IDENTITY, __VA_ARGS__)(LAM_CAT(LAM_PREFIX, __COUNTER__))
// Defines a function.
// Usage: `LAM_FUNC(ret)(name)(params)(body)`.
#define LAM_FUNC(...) LAM_DEFINE(LAM_NULL, __VA_ARGS__)
// `LAM_LAMBDA` and `LAM_FUNC` only work inside of this macro.
#define LAM_ENABLE_LAMBDAS(...) \
LAM_END( LAM_GEN_LAMBDAS_A (c,__VA_ARGS__) ) \
LAM_END( LAM_GEN_CODE_A (c,__VA_ARGS__) )
// Processes lambdas and functions in the following parentheses.
#define LAM_NEST(...) )(open,)(c,__VA_ARGS__)(close,)(c,
// A loop. Returns the original code, with lambdas replaced with corresponding function names.
#define LAM_GEN_CODE_A(...) LAM_GEN_CODE_BODY(__VA_ARGS__) LAM_GEN_CODE_B
#define LAM_GEN_CODE_B(...) LAM_GEN_CODE_BODY(__VA_ARGS__) LAM_GEN_CODE_A
#define LAM_GEN_CODE_A_END
#define LAM_GEN_CODE_B_END
#define LAM_GEN_CODE_BODY(type, ...) LAM_CAT(LAM_GEN_CODE_BODY_, type)(__VA_ARGS__)
#define LAM_GEN_CODE_BODY_c(...) __VA_ARGS__
#define LAM_GEN_CODE_BODY_l(wrap, ret, name, ...) wrap(name)
#define LAM_GEN_CODE_BODY_open() (
#define LAM_GEN_CODE_BODY_close() )
// A loop. Generates lambda definitions, discarding all other code.
#define LAM_GEN_LAMBDAS_A(...) LAM_GEN_LAMBDAS_BODY(__VA_ARGS__) LAM_GEN_LAMBDAS_B
#define LAM_GEN_LAMBDAS_B(...) LAM_GEN_LAMBDAS_BODY(__VA_ARGS__) LAM_GEN_LAMBDAS_A
#define LAM_GEN_LAMBDAS_A_END
#define LAM_GEN_LAMBDAS_B_END
#define LAM_GEN_LAMBDAS_BODY(type, ...) LAM_CAT(LAM_GEN_LAMBDAS_BODY_, type)(__VA_ARGS__)
#define LAM_GEN_LAMBDAS_BODY_c(...)
#define LAM_GEN_LAMBDAS_BODY_l(wrap, ret, name, par, ...) static LAM_IDENTITY ret name par { __VA_ARGS__ }
#define LAM_GEN_LAMBDAS_BODY_open()
#define LAM_GEN_LAMBDAS_BODY_close()
I wanted to know if it was contraindicated to define functions parameters using a macro, knowing they could be variable. Does it break a coding convention ?
example:
#ifdef PREVIOUSLY_DEFINED_MACRO
# define PARAMETERS int a, long b
#else
# define PARAMETERS int a
#endif
void my_func(PARAMETERS)
{
...
}
Thanks !
The code is completely valid but, it's not a good coding practice.
Let's assume the following code snippet:
#ifdef PREV_DEFINED
#define ARGS int x, int y
#else
#define ARGS int x
#endif
#include <stdio.h>
// #define PREV_DEFINED
int func(ARGS) {
// In this context, only 'x' is available
// set by the macro
return (x + y); // ERROR, 'y' is undefined
// You need to make a different code, specifically for
// #ifdef PREV_DEFINED and #else
}
To solve this, you need to make two or more different functions within those #ifdef and #endif flags whose usage is controlled by the PREV_DEFINED macro that depends on how many parameters could be variadic. Eventually, this will make the code look worse.
In this example code a macro is either defined or commented out by the programmer in order to remove a function from the released software.
#include <stdio.h>
#define MACRO //or omitted
#ifdef MACRO
void Function(const char* str)
{
printf("%s\n", str);
}
#else
#define Function(str)
#endif
int main(void)
{
Function("hello world");
getchar();
return 0;
}
Is there anything wrong with this?
Even though your solution works, I prefer the following approach:
#include <stdio.h>
#define MACRO //or omitted
#ifdef MACRO
#define FUNCTION(a) Function(a);
#else
#define FUNCTION(a)
#endif
#ifdef MACRO
void Function(const char* str)
{
printf("%s\n", str);
}
#endif
int main(void)
{
FUNCTION("hello world")
getchar();
return 0;
}
Note: FUNCTION is the macro, Function is the actual name of the function
This works by defining the macro FUNCTION(a) to a call to Function(const char*) when MACRO is enabled. On the other hand, when MACRO is disabled, calls to FUNCTION(a) will be defined to nothing.
I tend to prefer this method since it would be easier to abstract away the macro used to define your call from the macro defining your function definition. You might have cases where in release mode you only need to remove some of the calls to Function. In that case the definition of Function() is still required. For example:
#include <stdio.h>
#define DEBUG //or omitted
#ifdef DEBUG
#define FUNCTION(a) Function(a);
#else
#define FUNCTION(a)
#endif
void Function(const char* str)
{
printf("%s\n", str);
}
int main(void)
{
// Call function with Hello World only in debug
FUNCTION("hello world")
getchar();
// Call function with goodbye world in both debug and release
Function("goodbye world");
return 0;
}
It will work. But the entire symbol is removed this way. I prefer the following method.
#include <stdio.h>
#define MACRO 1
#if MACRO
void Function(const char* str)
{
printf("%s\n", str);
}
#else
void Function(const char *str){}
#endif
int main(void)
{
Function("hello world");
getchar();
return 0;
}
The following has changed:
The #if now compares a boolean. Your IDE is now able to find where MACRO is defined, in all cases. (right click, find definition)
You can, by changing MACRO to 2, change the entire meaning of Function. For example, a release compiled variant might contain a print to file or system log.
There will always be a symbol for Function, even if it does nothing, even in compiled code. This has the benefit that the string literals in the argument still count to the size statistics. As an embedded developer, I find this important.
Obviously, this is partly the preference of the one who crafts the code.
I want to define a constant depending on the OS in use.
As such:
#include <stdio.h>
#ifdef _Win32 //Used for system("cls") command
#include <process.h>
#define CLEAR "system(\"cls\")"
#endif
#ifdef __APPLE__
#define CLEAR "system(\"clear\")"
#endif
int main()
{
CLEAR;
}
Xcode gives me an error stating that expression result unused at
#define CLEAR "system(\"clear\") and inside the main function.
I am on a Mac.
Use:
#define CLEAR system("clear")
not
#define CLEAR "system(\"clear\")"
You get the error because your macro call is substituted with:
"system(\"clear\")";
which is a useless expression statement (the expression being the string here) like for example:
0; // valid but pointless
try altering your main function as such:
int main()
{
int rc;
rc = CLEAR;
return rc;
}
You need to catch the return value of the system() call and use it
#define CLEAR system("clear")
and not
#define CLEAR "system(\"clear\")"
The compiler will create a new C code (called pre-processor code) in which will replace the macro name by its content.
so if you define macro in this way:
#define CLEAR "system(\"clear\")"
You will get in the new code (pre-processor code) generated by the Compiler:
int main()
{
"system(\"clear\")";
}
You can see the code generated by the compiler (pre-processor code) with gcc -E