Default values on arguments in C functions and function overloading in C - c

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

Related

Printing only integer arguments in variable argument function in C

I want to write a C function, which can take any number of arguments and print value of int arguments only. I saw va_list and va_arg in stdarg.h, but I couldn't find any mechanism to get the number of arguments. I cannot take first argument as the number of arguments.
There's no portable way in standard C to get the number of arguments in variable argument functions.
The common way to solve it is to use the rightmost parameter parmN to provide the number of integers explicitly. For instance, your function prototype may look like this:
int foo(int number, ...);
But this is not an option to you according to your question.
Reference: C FAQ: How can I discover how many arguments a function was actually called with?
There is no (portable) way to get the number of arguments in a variadic function at runtime. That number is lost at runtime (only the compiler knows it).
Notice that on common processors and application binary interfaces (ABI) convention (e.g. x86-64 ABI on Linux), the machine itself does not know at runtime the arity of the current call in C; this is also true for others x86 calling conventions. However, when the compiler is compiling a variadic call, it does know the arity at compile time (but does not emit it in the object file).
You could define the convention that your variadic function takes as first argument the number of remaining (variadic) arguments:
void print_integers (int nbints, ...);
Then you would implement it e.g.
#include <stdio.h>
#include <stdarg.h>
void print_integers (int nbints, ...)
{
va_list args;
va_start (nbints, args);
for (int ix=0; ix<nbints; ix++) {
int curarg = va_arg(args, int);
printf(" %d", curarg);
};
va_end(args);
fflush(NULL);
}
If you cannot do this, you have to customize your preprocessor or your compiler. Perhaps a job for your MELT extension (MELT is a domain specific language to extend GCC). Or perhaps use GPP as your preprocessor.
You could also play some cpp preprocessor tricks, notably stringification and concatenation and variadic macros. For instance, you might define
void print_integers_str(const char*, ...);
#define print_my_integers(...) \
print_integers_str(#__VA_ARGS__, ##__VA_ARGS__);
Then print_my_integers(x,y) gets expanded to print_integers_str("x,y", x,y) and your varadic function print_integer_str could parse the "x,y" literal string (at least count commas). But with print_my_integers(f(x,y),g(y)+/*,,*/k)you may get a nightmare.
To be short: I recommend give up that goal and do things otherwise.
Using NARGS macro (in this case limited to 8 args):
#include <stdio.h>
#include <stdarg.h>
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define fn(...) fn(NARGS(__VA_ARGS__), __VA_ARGS__)
static void (fn)(int n, ...)
{
va_list args;
int i;
va_start(args, n);
for (i = 0; i < n; i++) {
printf("%d\n", va_arg(args, int));
}
va_end(args);
}
int main(void)
{
fn(6, 7, 8);
return 0;
}
Or you can loop until -1:
#include <stdio.h>
#include <stdarg.h>
#define fn(...) fn(0, __VA_ARGS__, -1)
static void (fn)(int n, ...)
{
va_list args;
int i;
va_start(args, n);
while (1) {
i = va_arg(args, int);
if (i == -1) break;
printf("%d\n", i);
}
va_end(args);
}
int main(void)
{
fn(6, 7, 8);
return 0;
}

Create a C function that accepts parameters of different data types

I'm relatively new to the C programming language, and I'm trying to figure out how to create a function that can accept different types of data as parameters. The function is supposed to count and return the number of elements in a character or integer array. I already have two separate functions that will do this, but I would really like to be able to use one function for both tasks. Is there a way to do this in C?
Thanks in advance!
There is no standard function overloading in C (nor are there templates), but you could probably look into "printf-like" functions (or variadic functions) and maybe they can do what you need. If anything they allow for a flexible parameter list.
There is an example here of such a function that takes a variable size integer array.
Perhaps you could have a function signature such as void iterate(const char* format, ...); that you use in the following ways:
iterate("char", some_char_array); // for char arrays/strings
Or
iterate("int", some_int_array); // for integer arrays
Aniket makes a good point though, how do you count the elements in an integer array? If you pass an int array as an argument, you would need to pass the size too which defeats the purpose of counting the elements in the array (as you already know that i.e. the size).
I assume you don't know the size but you have a terminator value in the array (such as -1).
I've hacked something quick that kinda does what you need with the above assumption in mind.
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
int iterate(const char* format, ...)
{
va_list ap;
va_start(ap, format);
if (strcmp(format, "char") == 0)
{
char* array = va_arg(ap, char*);
va_end(ap);
return strlen(array);
}
else if (strcmp(format, "int") == 0)
{
int j = -1;
int* int_array = va_arg(ap, int*);
while (int_array[++j] != -1)
;
va_end(ap);
return j;
}
va_end(ap);
return 0;
}
int main()
{
printf("%d\n", iterate("char", "abcdef"));
int arr[] = {5, 4, 3, 2, 1, 0, -1};
printf("%d\n", iterate("int", arr));
return 0;
}
This prints:
$ ./a.out
6
6
So, let's assume your two functions are called sizeof_char_array and sizeof_int_array.
In C11, there is a new feature called "generic selection" that will let you do what you want with a relatively simple macro:
#define sizeof_array(X) \
_Generic (*(X), \
char: sizeof_char_array, \
default: sizeof_int_array) (X)
(I don't even have a C11 implementation to test this against, so caveat emptor!)
Prior to C11, this was sometimes accomplished with a macro using regularly named functions. You can define a macro that will call one function or the other depending on a macro argument hint:
#define sizeof_array(xtype, x) sizeof_ ## xtype ##_array(x)
int a[] = { 1, 2, 3, 4, -1 };
char b[] = "abc";
sizeof_array(int, a); /* macro expands to sizeof_int_array(a) */
sizeof_array(char, b); /* macro expands to sizeof_char_array(b) */
If the input argument is truly an array, you can use a macro to compute its size directly:
#define ARRAY_SZ(x) (sizeof(x)/((void *)x == &x ? sizeof(x[0]) : 0))
In the case of an array, the following expression is true:
(void *)arr == &arr
Because the address of an array has the same location in memory as the address of its first element.
So, the macro computes: sizeof(arr)/sizeof(arr[0]). Since the sizeof operator reports the size in bytes of its argument, the computed expression results in the number of elements in the array. However, if you are using a sentinel to compute the length, the ARRAY_SZ macro will result in a size at least one larger than the length found traversing the array for the sentinel.
In the case that the argument is not an array, then the expression results in a divide by 0 exception.
The answer is quite simple. You do need a function for this task. Just try this piece of code
#define len(array) sizeof(array)/sizeof(*array)
and that's it.
Important note: As pointed out in the comments, this will not work for dynamically allocated arrays.
You should make your function arguments take in a void * type. This way, you can pass in different types of data, and type-cast it to the one you want. However, you do need to watch out because there is no guaranteed way to correctly 'guess' the type that a void* points to.
In either case, you will need some sort of type-inferencing system to tell the C compiler which function to call. Which means, you will need to know, before-hand the type of array you might send in as a parameter to this "super function" of yours.
There is no "auto-type-inferencing" in C that can let you reflect upon the type of data at runtime. Better yet, you might have to write your own runtime environment for this to happen.
A slightly trivial hackish way to do this:
#include <stdio.h>
size_t GetLengthOfArray(size_t sizeOfOneElementInArray, size_t sizeOfTheArrayInBytes)
{
return sizeOfTheArrayInBytes/sizeOfOneElementInArray;
}
int main(int argc, char *argv[])
{
char cArr[10] = {'A','B','C','D','E','F','G','H','I','J'};
int iArr[5] = {10,20,30,40,50};
printf("%d is the length of cArr\n%d is the length of iArr",GetLengthOfArray(sizeof(cArr[0]),sizeof(cArr)),
GetLengthOfArray(sizeof(iArr[0]),sizeof(iArr)));
return 0;
}
It's not really possible, but you can make a tagged union
typedef struct {
union {
ssize_t i;
double d;
char *s;
} unknown;
char identity;
} Dynamic;
Or you can use a void pointer:
typedef struct {
void *unknown;
char identity;
} Dynamic;

how only some arguments to function C

I have this function:
void func(int a, int b, char s, FILE *fp, int flag)
and i want to use the function's args based on the flag. For example:
func(num, NOTHING, NOTHING, file, 1)func(num, othernum, NOTHING, NOTHING, 2)and on the function this_is_function i want to have:
void func(int a, int b, char s, FILE *fp, int flag){
if(flag == 1){
/* use a and file */
}
if(flag == 2){
/* use a,b */
}
/* etc etc */
}
i would like to know if it is possible and how to do this!Thanks in advance :)
If by NOTHING you mean that you really want to omit that argument, I don't think it's possible the way you've outlined it.
The way this typically is done in C is through variable argument lists. That would mean you'd have to reformulate so that the flag goes first, since it decides the rest of the arguments:
void func(int flag, ...)
{
va_list args;
int num, othernum;
FILE *file;
va_start(args, flag);
if(flag == 1)
{
num = va_arg(args, int);
file = va_arg(args, FILE *);
}
else if(flag == 2)
{
num = va_arg(args, int);
othernum = va_args(args, int);
}
va_end(args);
/* Inspect `flag` again, and do things with the values we got. */
}
Then you can use the function like so:
func(1, 42, a_file);
or
func(2, 17, 4711);
This of course requires lots of care, since you're not getting a lot of help from the compiler anymore to match the values provided in the call to what the function expects.
I would recommend restructuring it into different top-level functions instead, that call a common "worker" function with the proper arguments:
func_mode1(42, a_file);
func_mode2(17, 4711);
these could then call func() with the proper flag value, filling in suitable defaults for arguments that don't apply (such as NULL for a non-used file pointer).
You can pass 0 to int and char and NULL for pointers when you call the function and the arguments are not used.
func(num, 0, 0, file, 1)
func(num, othernum, 0, NULL, 2)
You can also use variadic functions. Variadic functions are functions with a variable number of arguments.
Create seperate functions for each of the cases you are trying to handle. This would yield to more readable code. State your intention through your code rather than hack around it.
Your code should work fine and moreover try it out once and check for any errors. I am sure as no error should occur. You can also try using switch case in the func with flag as the choice for switch. I am sure you are not going to use Nothing and othersum in your code.

Functions with variable arguments. How does open() work?

I have to write a function that accepts a variable number of arguments, similar to the open() function
int open (const char *filename, int flags[, mode_t mode])
I had a look at the va_list functionality, but how can I find out how many arguments the user has supplied? I dont want to have a parameter in the function that indicates this.
Being a sort of newbie, where can I look how the open() function is implemented? How does open() know whether the user has supplied the mode argument or not?
Thanks in advance.
You cannot. The caller must either supply a trailing sentinel argument (e.g. a 0), or explicitly tell the function how many arguments to expect (e.g. the format fields in printf).
open knows to expect the third argument because you will have set the O_CREAT flag in the flags argument.
Copied straight from the GCC page.
Here is a complete sample function that accepts a variable number of arguments. The first argument to the function is the count of remaining arguments, which are added up and the result returned. While trivial, this function is sufficient to illustrate how to use the variable arguments facility.
#include <stdarg.h>
#include <stdio.h>
int
add_em_up (int count,...)
{
va_list ap;
int i, sum;
va_start (ap, count); /* Initialize the argument list. */
sum = 0;
for (i = 0; i < count; i++)
sum += va_arg (ap, int); /* Get the next argument value. */
va_end (ap); /* Clean up. */
return sum;
}
int
main (void)
{
/* This call prints 16. */
printf ("%d\n", add_em_up (3, 5, 5, 6));
/* This call prints 55. */
printf ("%d\n", add_em_up (10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
return 0;
}
What you're looking for is variadic function implementations. Here is a doc that will walk you through the entire chain.
The short answer to the question, "How does open know if it was passed two or three arguments?" is: it's magic. The long answer is that the implementation is allowed to do certain things that you are not (within standard C, that is).
Another example is main. It has two valid prototypes:
int main(void);
and
int main(int argc, char *argv[]); /* or equivalent */
The implementation must allow you to use any of the two, and "deduce", which is the one you used.
The answer to the question, "How can I do something similar in my code?", is: you can't, at least not within the constraints imposed by the C standard.

Do C functions support an arbitrary number of arguments?

PHP has a func_get_args() for getting all function arguments, and JavaScript has the functions object.
I've written a very simple max() in C
int max(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
I'm pretty sure in most languages you can supply any number of arguments to their max() (or equivalent) built in. Can you do this in C?
I thought this question may have been what I wanted, but I don't think it is.
Please keep in mind I'm still learning too. :)
Many thanks.
You could write a variable-arguments function that takes the number of arguments, for example
#include <stdio.h>
#include <stdarg.h>
int sum(int numArgs, ...)
{
va_list args;
va_start(args, numArgs);
int ret = 0;
for(unsigned int i = 0; i < numArgs; ++i)
{
ret += va_arg(args, int);
}
va_end(args);
return ret;
}
int main()
{
printf("%d\n", sum(4, 1,3,3,7)); /* prints 14 */
}
The function assumes that each variable argument is an integer (see va_arg call).
Yes, C has the concept of variadic functions, which is similar to the way printf() allows a variable number of arguments.
A maximum function would look something like this:
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
static int myMax (int quant, ...) {
va_list vlst;
int i;
int num;
int max = INT_MIN;
va_start (vlst, quant);
for (i = 0; i < quant; i++) {
if (i == 0) {
max = va_arg (vlst, int);
} else {
num = va_arg (vlst, int);
if (num > max) {
max = num;
}
}
}
va_end (vlst);
return max;
}
int main (void) {
printf ("Maximum is %d\n", myMax (5, 97, 5, 22, 5, 6));
printf ("Maximum is %d\n", myMax (0));
return 0;
}
This outputs:
Maximum is 97
Maximum is -2147483648
Note the use of the quant variable. There are generally two ways to indicate the end of your arguments, either a count up front (the 5) or a sentinel value at the back.
An example of the latter would be a list of pointers, passing NULL as the last. Since this max function needs to be able to handle the entire range of integers, a sentinel solution is not viable.
The printf function uses the former approach but slightly differently. It doesn't have a specific count, rather it uses the % fields in the format string to figure out the other arguments.
In fact, this are two questions. First of all C99 only requires that a C implementation may handle at least:
127 parameters in one function
definition
127 arguments in one function call
Now, to your real question, yes there are so-called variadic functions and macros in C99. The syntax for the declaration is with ... in the argument list. The implementation of variadic functions goes with macros from the stdarg.h header file.
here is a link to site that shows an example of using varargs in c Writing a ``varargs'' Function
You can use the va_args function to retrieve the optional arguments you pass to a function. And using this you can pass 0-n optional parameters. So you can support more then 2 arguments if you choose
Another alternative is to pass in an array, like main(). for example:
int myfunc(type* argarray, int argcount);
Yes, you can declare a variadic function in C. The most commonly used one is probably printf, which has a declaration that looks like the following
int printf(const char *format, ...);
The ... is how it declares that it accepts a variable number of arguments.
To access those argument it can uses va_start, va_arg and the like which are typically macros defined in stdarg.h. See here
It is probably also worth noting that you can often "confuse" such a function. For example the following call to printf will print whatever happens to be on the top of the stack when it is called. In reality this is probably the saved stack base pointer.
printf("%d");
C can have functions receive an arbitrary number of parameters.
You already know one: printf()
printf("Hello World\n");
printf("%s\n", "Hello World");
printf("%d + %d is %d\n", 2, 2, 2+2);
There is no max function which accepts an arbitrary number of parameters, but it's a good exercise for you to write your own.
Use <stdarg.h> and the va_list, va_start, va_arg, and va_end identifiers defined in that header.
http://www.kernel.org/doc/man-pages/online/pages/man3/stdarg.3.html

Resources