I am writing a generic function which will take macro name and execute correct function.
I am writing a function which will take function name from macro and concatenate this and execute the function.I am adding this header file in my workspace where more than one c file use this macro implementation logic to execute my code.But I am getting error while running the code .
#define STR(name) #name
int convert_f14u18(int a,int b);
int convert_f14s18(int a,int b);
#define VAL_F 14
#define DATA_SIGN u
#define VAL_NUM 18
#define EXECUTE_FUN_NAME(a,b,c,d,e) a##b##c##d##e
#define EXECUTE_STATEMENT(a,b,c,d,e,f) b##c##d##e#f=EXECUTE_FUN_NAME(a,b,c,d,e)
typedef int u32;
u32 add_u32(u32 a,u32 b);
int main() {
//Testing of string macro
printf(STR(Hello));
int numa = 10;
int numb = 20;
int numc = 30;
//int z1 = EXECUTE_FUN_NAME(convert_,f,14,u,18)(numa,numb);
int z1 = EXECUTE_FUN_NAME(convert_,f,VAL_F,DATA_SIGN,VAL_NUM)(numa,numb);
//int z2 = EXECUTE_FUN_NAME(convert_,f,14,s,18)(numa,numc);
int z2 = EXECUTE_FUN_NAME(convert_,f,VAL_F,DATA_SIGN,VAL_NUM)(numa,numc);
printf("\nz1 %d\n",z1);
printf("z2 %d\n",z2);
return 0;
}
int convert_f14u18(int a,int b){
return (a+b);
}
int convert_f14s18(int a,int b){
return (a+b);
}
u32 add_u32(u32 a,u32 b){
return (a+b);
}
Error:../main.cpp: In function ‘int main()’:
../main.cpp:37:76: error: ‘convert_fVAL_FDATA_SIGNVAL_NUM’ was not declared in this scope
int z1 = EXECUTE_FUN_NAME(convert_,f,VAL_F,DATA_SIGN,VAL_NUM)(numa,numb);
Expected result: If I un-comment the lines above of actual macro statement in main statements and comment the current macro statements, I am able to run the code. But I want to make my code run with the current logic .
When replacing a macro, C first replaces each parameter with its argument. So the argument c is replaced with VAL_F, for example. Then it applies the ## operator, which produces convert_fVAL_FDATA_SIGNVAL_NUM in this example. Then C checks the result for additional macros to substitute. However, at that point, the arguments, such as VAL_F, have been made into a single token with ## and are no longer individual tokens that will be replaced.
To deal with this, use one macro to replace the arguments, then use another macro to apply the ## operator. Change:
#define EXECUTE_FUN_NAME(a,b,c,d,e) a##b##c##d##e
to:
#define EXECUTE_FUN_NAME_HELPER(a, b, c, d, e) a##b##c##d##e
#define EXECUTE_FUN_NAME(a, b, c, d, e) EXECUTE_FUN_NAME_HELPER(a, b, c, d, e)
Related
I am looking to use the _Generic preprocessor directive to achieve function overloading. I learned to use it from this wonderfully detailed answer.
However, it doesn't seem to cover this case:
#include <stdio.h>
void foo_one(int);
void foo_two(int, float*);
#define FIRST_VARG(_A, ...) _A
#define foo(_X, ...) _Generic( (FIRST_VARG(__VA_ARGS__,)), \
float* : foo_two, \
default : foo_one) (_X, __VA_ARGS__)
void foo_one(int A)
{
printf("FOO ONE: %d\n", A);
}
void foo_two(int A, float* B)
{
printf("FOO TWO: %d, %f", A, *B);
}
void main()
{
float x = 3.14;
float* y = &x;
foo(1); // This statement pops an error
foo(2, y);
}
Here, you can see that the first argument to both functions is an integer. However, the second argument of the second function is a float*. Visual Studio complains about the calling foo(1), but not when calling foo(2, y). The error is
error C2059: syntax error: ')'
I know Visual Studio can support _Generic with a small trick. So, I feel like there is something I am doing wrong. There is a comment in the answer where I learned about _Generic that suggests using (SECOND(0, ##__VA_ARGS__, 0), etc. But I don't understand it.
Can someone walk me through how I could achieve my intended result?
There are two issues. First is selecting the second argument of foo for generic selection in the case when there is no second argument.
Other is #define foo(_X, ...) which will not work for foo(1) because the function macro expect two or more arguments. It often works but it a compiler specific extensions. Compiling in pedantic mode will raise a warning. See https://godbolt.org/z/z7czvGvbc
A related issue is expanding to (_X, __VA_ARGS__)which will not work for foo(1) where ... maps to nothing.
The both issues can be addressed with placing a dummy type (NoArg) at the end of the list prior to extracting the second argument. It will both extend the list and add a value that can be used by _Generic to correctly dispatch the function expression.
#include <stdio.h>
void foo_one(int);
void foo_two(int, float*);
typedef struct { int _; } NoArg;
// use compound literal to form a dummy value for _Generic, only its type matters
#define NO_ARG ((const NoArg){0})
#define foo_(args, a, b, ...) \
_Generic((b) \
,NoArg: foo_one \
,default: foo_two \
) args
// pass copy of args as the first argument
// add NO_ARG value, only its type matters
// add dummy `~` argument to ensure that `...` in `foo_` catches something
#define foo(...) foo_((__VA_ARGS__), __VA_ARGS__, NO_ARG, ~)
void foo_one(int A)
{
printf("FOO ONE: %d\n", A);
}
void foo_two(int A, float* B)
{
printf("FOO TWO: %d, %f\n", A, B ? *B : 42.0f);
}
#define TEST 123
int main(void)
{
float x = 3.14;
float* y = &x;
foo(1); // This statement pops an error
foo(2, y);
foo(TEST, NULL);
return 0;
}
The last issue is addressed by passing a tuple with original arguments as extra argument to foo_ macro, this argument is later passed to the call operator of expression selected by _Generic.
This solution works with all major C17 compilers (gcc, clang, icc, msvc).
I have a function in my program that takes 3 arguments. Some times in the code there is a macro defining 2 of these parameters.
So this:
void func(int x, int y, int z){...}
Can be invoked like this:
#define PAR 10,20
int z = 3;
func(PAR, z);
Now, I need to change my code so that the function is called like a macro for another function.
#define func(X,Y,Z) func2(X,Y,Z,#Z)
This works fine if X and Y are really passed as variables. Is there any way to make it work also with the macro PAR?
I'm using GCC 4.6
You can do this with an extra level of indirection, (ab)using variadic
macros:
#include <stdio.h>
#define PAR 2,3
#define F(...) G(__VA_ARGS__)
#define G(a,b,c) H(a,b,c)
void H(int a, int b, int c) {
printf("%d %d %d\n", a , b, c);
}
int main() {
F(PAR, 42);
return 0;
}
There is probably a better solution for the underlying problem.
No, I don't believe so. When you define
#define func(X,Y,Z) func2(X,Y,Z,#Z)
You're defining a function-like macro. func(X,Y,Z) actually takes three arguments - and it has to take three arguments. Remember, the preprocessor and not the compiler is interpreting func(PAR, Z).
I've struggled to find any documentation, but it makes sense that the first thing the preprocessor will do (considering that func() is the outer element) is to check to see if the arguments to func() are valid. Then it will place the arguments into func2() and will then expand any macros that were passed as arguments. The code I placed below seems to back up this claim.
Following this logic, the preprocessor will see that func(PAR, Z) isn't a valid call because an argument is missing, which will then throw the error
13:12: error: macro "func" requires 3 arguments, but only 2 given
func(X, Y, Z) will work so long as X and Y are valid macros or variables.
Code (this will give you warnings because there is no function declaration, but the output will be "3 14 3" as expected):
#include <stdio.h>
#include <stdlib.h>
#define PAR 10,20
#define MAR 3
#define WAR 14
#define func(X,Y,Z) print(X, Y, Z)
int Z = 3;
int main(void){
func(MAR,WAR,Z);
return 0;
}
void print(int x, int y, int c){
printf("%d %d %d\n", x, y, c);
}
Out of curiosity, why are you doing this (I don't have enough reputation to comment yet FYI).
I have a call to a function foo(a,b,c) in a C file which I want to prepend with some code. Can I do this with macro? Basically, I want to do the following:
Replace
add(a,b,c)
by
foo()
add(a,b,c)
Is it possible to achieve this with macro?
#include <stdio.h>
int add(int a, int b, int c) {
return a + b + c;
}
void foo() {
printf("Foo!\n");
}
int add2(int a, int b, int c) {
foo();
return add(a, b, c);
}
#define add(a, b, c) add2((a), (b), (c))
int main() {
printf("%d\n", add(5, 3, 1));
return 0;
}
As macros don't expand recursively, the following is possible:
#define add(a, b, c) ( foo() , add((a), (b), (c)) )
The add in the replacement refers to the function, not the macro. This approach, however, has a few pitfalls: Taking the address and using a function pointer will refer to the real function, not the macro, as would enclosing add in parentheses as in (add)(a, b, c).
Sure you can define a macro
#define foo(a,b,c) {foo(); add(a,b,c);}
If C++ inline function is not an option then use comma operator:
#define bar(a, b, c) (foo(), add((a), (b), (c)))
I want to pass a macro as an argument in a C function, and I don't know if it possible.
I would like to see this operation, for instance:
I have these macros:
#define PRODUCT(A, B) ((A) * (B))
#define SUM(A, B) ((A) + (B))
And then I have this function with the following signature:
int just_a_function(int x, MACRO_AS_PARAMATER_HERE);
and then i want to call this function like:
just_a_function(10, SUM);
is it possible?
Thanks
You can't pass as function argument.
But if function is a macro this is possible.
#include <stdio.h>
#define PRODUCT(A, B) ((A) * (B))
#define SUM(A, B) ((A) + (B))
#define JUST_A_FUNCTION(A, B, MACRO) MACRO(A, B)
int main() {
int value;
value = JUST_A_FUNCTION(10, 10, SUM);
printf("%d\n", value);
value = JUST_A_FUNCTION(10, 10, PRODUCT);
printf("%d\n", value);
return 0;
}
You can't do that.
Use normal functions instead:
int sum(int x, int y)
{
return x+y;
}
//...
just_another_function(10, sum);
Note: just_another_function must accept int (*)(int, int) as the second argument.
typedef int (*TwoArgsFunction)(int, int);
int just_another_function(int x, TwoArgsFunction fun);
Hi what you are passing is macro means its a substitution your passing . Think about it ..
Ex : #define HIGH 1
In a function you can use int variable. So you can pass 1 to the function . In a function its stored as integer variable
Preprocessor directive works first . Once in a main macro are replaced means in the sense in a function you have to take care of the substitution. If I would have used Macro High 1 ,, in function I will take as int as a argument to get for local function stack. For better understanding check the topics 1.preprocessor directive 2. How the hex file created once you will compile
#include <stdio.h>
#define HIGH 1
#define LOW 0
void pin(int, int);
void pin(int a, int b) {
printf("A: %d B: %d\n", a, b);
}
int main() {
pin(1, HIGH);
return 0;
}
Compilation step involve:
pre processor directive
compiler
linker
executable file
I want to write several functions that are only different in the types of arguments. I know C++ has template to handle this problem well (not very well yet though, few compilers support export keyword and this keyword is queried for efficiency). For easy example, I want:
template <typename T>
T add(T a, T b){
return a+b;
}
However, in pure C (sometimes I have to choose pure C, as some platform doesn't have the C++ compiler), there have to be different function names for different versions, as
double addDouble(double a, double b){
return a+b;
}
int addInt(int a, int b){
return a+b;
}
Hmmm, when there are two versions, it seems OK that I can do the copy-and-paste work in a source file; However, in practice there would be many lines instead of just a return statement in a function and would be more versions. So, my question is, how to implement a series of functions in different type versions elegantly?
So far I have tried some solutions as below, but I think they are far from good. I need your suggestions, thank you!
Solution 1:
#define mytype int
mytype addInt(mytype a, mytype b){
return a+b;
}
#undef mytype
#define mytype float
mytype addFloat(mytype a, mytype b){
return a+b;
}
#undef mytype
Shortcoming of Solution 1: duplicated contents are too many, and if I want to modify the function, I have to modify all of versions.
Solution 2:
func.h
#ifndef FUNC_H
#define FUNC_H
#define add(a, b, typename) functionAdd##typename(a,b)
/* function declarations */
#define declared(typename) \
typename functionAdd##typename(typename, typename)
declared(int);
declared(float);
#endif
func.c
#include "func.h"
/* function code */
#define functionAdd(a, b, typename) \
typename functionAdd##typename(typename a, typename b){ \
return a+b; \
}
/* function bodies (definitions) */
functionAdd(a, b, int)
functionAdd(a, b, float)
main.c
#include <stdio.h>
#include "func.h"
int main()
{
int x1 = add(1, 2, int);
float x2 = add(3.0, 4.0, float);
printf("%d %f\n", x1, x2);
return 0;
}
Shortcoming of Solution 2: Because the function is written in define, it's difficult to debug. Besides, the \ notation is annoying. Though, it's convenient to add a new version, just inserting declared(double) into func.h and functionAdd(a, b, double) into func.c will achieve this aim.
In many (if not most) cases the best way to simulate C++ templates in C would be Solution 3: parametrized header file and parametrized implementation file. In your case it would work as follows
Create a meta-header file, which we'll name add.dec, that looks as follows
TYPE_ CONCAT(add, SUFFIX_)(TYPE_ a, TYPE_ b);
TYPE_ CONCAT(sub, SUFFIX_)(TYPE_ a, TYPE_ b);
Create a meta-implementation file, which we'll name add.def, that looks as follows
TYPE_ CONCAT(add, SUFFIX_)(TYPE_ a, TYPE_ b){
return a + b;
}
TYPE_ CONCAT(sub, SUFFIX_)(TYPE_ a, TYPE_ b){
return a - b;
}
These two files are parametrized by two macros: TYPE_ and SUFFIX_, while CONCAT is a traditional implementation of macro concatenation
#define CONCAT_(a, b) a##b
#define CONCAT(a, b) CONCAT_(a, b)
Now, imagine you want to instantiate your "template" functions for types int and double. In a "real" header file add.h you simply do
#define TYPE_ int
#define SUFFIX_ Int
#include "add.dec"
#undef TYPE_
#undef SUFFIX_
#define TYPE_ double
#define SUFFIX_ Double
#include "add.dec"
#undef TYPE_
#undef SUFFIX_
and in a "real" implementation file add.c you do
#define TYPE_ int
#define SUFFIX_ Int
#include "add.def"
#undef TYPE_
#undef SUFFIX_
#define TYPE_ double
#define SUFFIX_ Double
#include "add.def"
#undef TYPE_
#undef SUFFIX_
That's it. By doing this you instantiated (declared and defined) addInt, addDouble, subInt and subDouble.
Of course, you can parametrize the declarations much more. You can add a DECLSPEC_ parameter to be able to declare your sunctions as static, if necessary. You can specify different types for parameters and return values (say, ARG_TYPE_ and RET_TYPE_). You can parametrize lots of other things. Basically, there's no limit to what you can parametrize. With some fairly easy macro techniques you can even parametrize the number of parameters your functions expect.
This is actually similar to your Solution 1 and Solution 2 combined. This basically takes the best from both of your approaches. And I'd say that this is the most faithful attempt to simulate the behavior of C++ template instantiation.
Note that each function's body is explicitly typed only once (as opposed to multiple explicit copies in your Solution 1). The actual function bodies are also easily editable, since there's no need to worry about those pesky \ at the end of each line (as is the case in your Solution 2).
This approach has another interesting benefit: the code in add.def will remain "debuggable", i.e. an ordinary interactive debugger will typically be able to step into these implementations (which is impossible in your Solution 2).
I would also propose Solution 4: write a code generation tool.
Pros:
result is a clean debuggable code;
unlimited configurability to your needs (if you have time of course);
long-term investment to a dev's toolset.
Cons:
takes some time, esp. at start, not always sutable for write-once code;
complicates build process a bit.
If you think using the C preprocessor is awkward and hard to debug, how about writing a script in some more convenient language to generate a .c file you can #include? Most modern scripting languages come with some sort of template engine, but since your requirements are simple enough, it doesn't have to be any more complex than this;
#/bin/sh
for t in int double char mytype; do
cat <<____HERE
$t add_$t ($t a, $t b) {
return (a + b);
}
____HERE
done >generated.c
The resulting file will be plain-jane straightforward C which should be reasonably simple to debug and change.
You can use union:
#include <stdio.h>
#include <stdarg.h>
typedef enum {Int, Double} NumberType;
typedef struct {
NumberType type;
union {
int i;
double d;
};
} Number;
Number addNumber(Number a, Number b) {
Number ret;
Number *numbers[] = {&a, &b};
if (a.type == Int && b.type == Int ){
ret.type = Int;
ret.i = a.i + b.i;
}
else {
ret.type = Double;
char i;
for (i = 0; i < 2 && numbers[i]->type == Int; i++) {
numbers[0]->d = (double) numbers[i]->i;
}
ret.d = a.d + b.d;
}
return ret;
}
Number newNumber(NumberType type, ...) {
va_start(ap, type);
Number num;
num.type = type;
switch (type) {
case Int: {
num.i = va_arg(ap, int);
break;
}
case Double: {
num.d = va_arg(ap, double);
break;
}
default: { /* error */
num.type = -1;
}
}
va_end(ap);
return num;
}
int main(void) {
Number a = newNumber(Int, 1);
Number b = newNumber(Double, 3.0);
Number ret = addNumber(a, b);
switch (ret.type) {
case Int: {
printf("%d\n", ret.i);
}
case Double: {
printf("%f\n", ret.d);
}
}
return 0;
}
I don't think you can do much better than your solution 2 in pure C.