Related
I have two functions foo1(a,b) & foo2(a,b,c) and a macro
#define add(a,b) foo(a,b)
I need to re-define macro to accomplish,
1.if add() is called with 2 parameters, then call foo1
if add() is called with 3 parameters then call foo2
Im new to the option VA_ARGS. How can I do that
If you just want to distinguish between two functions, the following works:
#define ADD(_1, _2, _3, X, ...) X
#define add(...) ADD(__VA_ARGS__, add3, add2, 0)(__VA_ARGS__)
The auxiliary macro ADD always picks the fourth argument:
add(a, b) --> ADD(a, b, add3, add2, 0) --> add2
add(a, b, c) --> ADD(a, b, c, add3, add2, 0) --> add3
The drawback is that you get quite cryptic error messages when you don't supply two or three arguments to the function.
The advantage over variadic functions is that you get type safety. For example if your functions operate on doubles, you can still say add(1, 2) and the integer arguments will be converted to doubles. And variadic functions require some additional information on the number of actual arguments, so that's not a feasible solution here, unless you specify the number of summands in the function.
Addendum: I've changed the add macro so that it doesn't pass an empty variadic list to ADD. Some compilers allow empty lists, but it isn't standard C.
That usual trick for counting arguments may be adapted for this:
#define ADD_EXPAND(...) \
ADD_EXPAND_(__VA_ARGS__, EXPAND_ADD_FUNCS())
#define ADD_EXPAND_(...) \
EXPAND_ADD_SEL_FUNC(__VA_ARGS__)
#define EXPAND_ADD_SEL_FUNC(first_, second_, third_, func, ...) func
#define EXPAND_ADD_FUNCS() foo2, foo, dummy
#define add(...) ADD_EXPAND(__VA_ARGS__)(__VA_ARGS__)
Once you plow through the boiler plate, it basically just involves placing all the arguments in a line, with the function tokens after them, and seeing which function stands out. That's what EXPAND_ADD_SEL_FUNC does.
You can see it live on coliru.
But I'll reiterate what we told you in comments. This is likely to be a sub-par solution to a proper function. I haven't tested it thoroughly, so breakage is easily possible. Use at your own risk.
If you must use variadic macros, then here is a trick.
#define add(...) _Generic ( &(int[]){__VA_ARGS__}, \
int(*)[2]: add2, \
int(*)[3]: add3) (__VA_ARGS__)
Have the macro create a compound literal array. The size of this array will depend on the number of arguments.
Grab the address of the compound literal, to get an array pointer type.
Let _Generic check which type you got, then call the proper function based on that.
This is 100% standard C and also type safe.
Demo:
#include <stdio.h>
#define add(...) _Generic ( &(int[]){__VA_ARGS__}, \
int(*)[2]: add2, \
int(*)[3]: add3) (__VA_ARGS__)
int add2 (int a, int b);
int add3 (int a, int b, int c);
int main (void)
{
printf("%d\n", add(1, 2));
printf("%d\n", add(1, 2, 3));
//printf("%d\n", add(1, 2, 3, 4)); Compiler error for this.
}
int add2 (int a, int b)
{
return a + b;
}
int add3 (int a, int b, int c)
{
return a + b + c;
}
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)))
As the title says, how do I use the pointer of a function in C? Can I just take the address of the function name and pass it to another function; then dereference it and call it?
Thanks a lot.
If you know the function address, then yes. For example:
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int operation(int (*op)(int, int), int a, int b)
{
return op(a, b);
}
Then just call it like this:
printf("%d\n", operation(&add, 5, 3)); // 8
printf("%d\n", operation(&sub, 5, 3)); // 2
You can even do some array tricks:
int op = 0;
int (*my_pointer[2])(int, int) =
{
add, // op = 0 for add
sub // op = 1 for sub
};
printf("%d\n", my_pointer[op](8, 2)); // 10
well to answer your question precisely, there is a provision in C for such needs which is called "function pointer".
But you have to follow certain rules,
1) All the functions you want to call using function pointer must have same return type.
2) All the functions you want to call using function pointer must have same no of arguments and argument types.
For example,
int add(int, int);
int sub(int, int);
for above two functions you can write function pointer as,
int (*operation)(int , int);
and you can use it just as described by Flavio Torbio.
hope it helps.....
Is it possible to set values for default parameters in C? For example:
void display(int a, int b=10){
//do something
}
main(){
display(1);
display(1,2); // override default value
}
Visual Studio 2008, complaints that there is a syntax error in -void display(int a, int b=10). If this is not legal in C, whats the alternative? Please let me know. Thanks.
Default parameters is a C++ feature.
C has no default parameters.
It is not possible in standard C. One alternative is to encode the parameters into the function name, like e.g.
void display(int a){
display_with_b(a, 10);
}
void display_with_b(int a, int b){
//do something
}
There are no default parameters in C.
One way you can get by this is to pass in NULL pointers and then set the values to the default if NULL is passed. This is dangerous though so I wouldn't recommend it unless you really need default parameters.
Example
function ( char *path)
{
FILE *outHandle;
if (path==NULL){
outHandle=fopen("DummyFile","w");
}else
{
outHandle=fopen(path,"w");
}
}
Not that way...
You could use an int array or a varargs and fill in missing data within your function. You lose compile time checks though.
If you are using a compiler compatible with C++2a, then there is a preprocessor trick that you can use, as explained at https://stackoverflow.com/a/10841376/18166707
You can use this code snippet as an example:
#include <stdio.h>
#define ADD_THREE(a,b,...) add_three_nums(a, b, (0, ##__VA_ARGS__))
int add_three_nums( int a, int b, int c)
{
return a + b + c;
}
void main( void )
{
printf("%d\n", ADD_THREE(3, 5));
printf("%d\n", ADD_THREE(4, 6, 8));
}
Converting a C++ lib to ANSI C and it seems like though ANSI C doesn't support default values for function variables or am I mistaken?
What I want is something like
int funcName(int foo, bar* = NULL);
Also, is function overloading possible in ANSI C?
Would need
const char* foo_property(foo_t* /* this */, int /* property_number*/);
const char* foo_property(foo_t* /* this */, const char* /* key */, int /* iter */);
Could of course just name them differently but being used to C++ I kinda used to function overloading.
No, Standard C does not support either. Why do you feel you need to convert your C++ code to C? That could get quite tricky - I'd have thought writing wrappers would be the way to go, if your C++ must be callable from C.
Nevertheless I found a "trick" to do so if you use GCC (edit December 2020) or any compiler compatible with C++2a -yes it works with 'plain C' since it is a pre-compiler trick-.
GCC has a handy ## extension on variadic macro that allows you to simulate a default argument.
The trick has limitations: it works only for 1 default value, and the argument must be the last of you function parameters.
Here is a working example.
#include <stdio.h>
#define SUM(a,...) sum( a, (5, ##__VA_ARGS__) )
int sum (a, b)
int a;
int b;
{
return a + b;
}
main()
{
printf("%d\n", SUM( 3, 7 ) );
printf("%d\n", SUM( 3 ) );
}
In this case, I define SUM as a call to sum with the default second argument being 5.
If you call with 2 arguments (first call in main), it would be prepocessed as:
sum( 3, (5, 7) );
This means:
1st argument is 3
second argument is the result of the sequence (5, 7)... which is
obviously 7!
As gcc is clever, this has no effect on runtime as the first member of the sequence is a constant and it is not needed, it will simply be discarded at compile time.
If you call with only one argument, the gcc extension will remove the VA_ARGS AND the leading coma. So it is preprocessed as:
sum( 3, (5 ) );
Thus the program gives the expected output:
10
8
So, this does perfectly simulate (with the usual macro limitations) a function with 2 arguments, the last one being optional with a default value applied if not provided.
Edit
-a) It does also work with CLANG (and possibly other compilers)
-b) A version that does NOT complain about unused arguments:
#define DEF_OR_ARG(z,a,arg,...) arg
#define SUM(a,...) sum( a, DEF_OR_ARG(,##__VA_ARGS__,__VA_ARGS__,5))
[Edit - October 2020] :
You could also try the new __VA_OPT__ that was standardised with c++2a (and should work in plain C too) instead of ## which is a gcc extension. Typical usage is __VA_OPT__(,) that would add the coma when the argument list is non-empty and otherwise outputs nothing.
[Edit - December 2020] :
So the above trick, with __VA_OPT__, becomes:
#define DEF_OR_ARG(value,...) value
#define SUM(a,...) sum( a, DEF_OR_ARG(__VA_ARGS__ __VA_OPT__(,) 5))
Unlike the 'sequence trick' that might complain for unused variables, this only involves the pre-compiler and is more readable.
When SUM is called with only one argument, ... is empty and __VA_OPT__ does not output anything, thus DEF_OR_ARG(__VA_ARGS__ __VA_OPT(,) 5) becomes DEF_OR_ARG( 5)
When SUM is called with a second argument, ... is this second argument and __VA_OPT__ expands to the value given which is a coma. In that case
DEF_OR_ARG(__VA_ARGS__ __VA_OPT(,) 5) becomes DEF_OR_ARG(second_argument_of_SUM , 5)
Now the expansion of DEF_OR_ARG happens. This one is easy since it considers only the first argument and just discards the rest.
So, when SUM was called with no second argument (first case above), the first argument to DEF_OR_ARG is our default value. In the case there was a second argument to SUM, it becomes the first argument to DEF_OR_ARG that will expand to that and discard the default which is now second argument.
Try this.
#include <stdio.h>
#include <stdarg.h>
/* print all non-negative args one at a time;
all args are assumed to be of int type */
void printargs(int arg1, ...)
{
va_list ap;
int i;
va_start(ap, arg1);
for (i = arg1; i >= 0; i = va_arg(ap, int))
printf("%d ", i);
va_end(ap);
putchar('\n');
}
int main(void)
{
printargs(5, 2, 14, 84, 97, 15, 24, 48, -1);
printargs(84, 51, -1);
printargs(-1);
printargs(1, -1);
return
0;
}
There is a way to support as many default parameters you need, just use a structure.
// Populate structure with var list and set any default values
struct FooVars {
int int_Var1 = 1; // One is the default value
char char_Command[2] = {"+"};
float float_Var2 = 10.5;
};
struct FooVars MainStruct;
//...
// Switch out any values needed, leave the rest alone
MainStruct.float_Var2 = 22.8;
Myfunc(MainStruct); // Call the function which at this point will add 1 to 22.8.
//...
void Myfunc( struct FooVars *MyFoo ) {
switch(MyFoo.char_Command) {
case '+':
printf("Result is %i %c %f.1 = %f\n" MyFoo.int_Var1, MyFoo.char_Command, MyFoo.float_Var2, (MyFoo.float_Var2 + MyFoo.int_Var1);
break;
case '*':
// Insert multiply here, you get the point...
break;
case '//':
// Insert divide here...
break;
}
}
As far as I know ANSI C doesn't directly support function overloading or default arguments. The standard substitute for overloading is adding suffixes to the function name indicating the argument types. For example, in OpenGL, a "3fv" suffix to a function name means the function takes a vector of three floats.
Default arguments can be viewed as a special case of function overloading.
Neither of default values or function overloading exists in ANSI C, so you'll have to solve it in a different way.
You can't so easily since C does not support them. The simpler way to get "fake overloading" is using suffixes as already said... default values could be simulated using variable arguments function, specifying the number of args passed in, and programmatically giving default to missing one, e.g.:
aType aFunction(int nargs, ...)
{
// "initialization" code and vars
switch(nargs)
{
case 0:
// all to default values... e.g.
aVar1 = 5; // ...
break;
case 1:
aVar1 = va_arg(arglist, int); //...
// initialize aVar2, 3, ... to defaults...
break;
// ...
}
}
Also overloading can be simulated using var args with extra informations to be added and passed and extracode... basically reproducing a minimalist object oriented runtime ...
Another solution (or indeed the same but with different approach) could be using tags: each argument is a pair argument type + argument (an union on the whole set of possible argument type), there's a special terminator tag (no need to specify how many args you're passing), and of course you always need "collaboration" from the function you're calling, i.e. it must contain extra code to parse the tags and choose the actual function to be done (it behaves like a sort of dispatcher)
You'll have to declare each C++ overloaded function differently in C because C doesn't do name mangling. In your case "foo_property1" "foo_property2".
i think u can use a function with variable arguments here is my example
#include <stdarg.h>
#include <stdio.h>
void baz( int flag, ... )
{
va_list ap;
char *bar = "baz"; /* default value */
va_start( ap, flag );
if ( flag == 1 )
bar = va_arg( ap, char * );
va_end( ap );
printf( "%s\n", bar );
}
int main( void )
{
baz( 0 );
baz( 1, "foo");
baz( 2 );
baz( 1, "bar");
return 0;
}
the output is
baz
foo
baz
bar
if u look for example man 2 open they say
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
int openat(int dirfd, const char *pathname, int flags);
int openat(int dirfd, const char *pathname, int flags, mode_t mode);
but mode is actually a ... argument