I'd like to write some functions in C but they have to be available for all numeric types (int, float, double). What is good practise? Use pointer on void (and pointer to function of course)? Or write a different function for every type?
For example:
float func(float a, float b) {
return a+b;
}
If you can use C11, _Generic can help:
#include <stdio.h>
int ifunc(int a, int b) { return a+b; }
float ffunc(float a, float b) { return a+b; }
double dfunc(double a, double b) { return a+b; }
#define func(x, y) \
_Generic((x), int: ifunc, float: ffunc, double: dfunc, default: ifunc)(x, y)
int main(void)
{
{
int a = 1, b = 2, c;
c = func(a, b);
printf("%d\n", c);
}
{
float a = .1f, b = .2f, c;
c = func(a, b);
printf("%f\n", c);
}
{
double a = .1, b = .2, c;
c = func(a, b);
printf("%f\n", c);
}
return 0;
}
As C does not have multiple dispatch (function overloading) like C++ (EDIT: unless you use C11, which has _Generic) , you have to name the functions for each type differently, like funcInt(int a, int b); funcFloat(float a, float b);
OR
use GCC style statement-expression macros which allow typeof() to kind of fake it.
The old style C way is to use a union and a discriminator:
union multi_num {
uint32_t small_num;
uint64_t large_num;
float float_num;
};
struct multi_type {
int discriminator;
union multi_num val;
};
int
add_fun (struct multi_type var1, struct multi_type var2, struct multi_type *ret_val)
{
if (var1.discriminator != var2.discriminator) {
return -1;
}
ret_val->discriminator = var1.discriminator;
switch (var1.discriminator) {
case 1:
ret_val->val.small_num = var1.val.small_num + var2.val.small_num;
break;
case 2:
ret_val->val.large_num = var1.val.large_num + var2.val.large_num;
break;
case 3:
ret_val->val.float_num = var1.val.float_num + var2.val.float_num;
break;
}
return 0;
}
Then you can call it like this:
struct multi_type var1, var2, var3 = {0};
var1.discriminator = 1;
var2.discriminator = 1;
var1.val.small_num = 1;
var2.val.small_num = 12;
ret = add_fun(var1, var2, &var3);
if (0 == ret) {
printf("add worked, ret is %d\n", var3.val.small_num);
} else {
printf("add failed\n");
}
In C++, this would have easily been done with templates or function overloading.
The only way I know in C is to write a different function for every type.
You can use a function taking two void* and compute with them, but it's extremely misleading for the user: what if there is a special type for which another version of the function is available but the user uses the void* function? This can lead to big problems, and is not recommended.
For a practical example of this, look at the standard string conversion functions atoi, atol, atof located in stdlib.h. One function per variable type.
Related
I have a union type declared as follows:
typedef union Data {
int i;
char c;
double d;
float f;
} data;
I know fields are overwritten by new values. I would like to know if there is any way to do the following instead of needing to manually access each field depending on the type of data I want to store:
data *c;
*c = 3; // instead of c.i = 3; c.i should be 3
*c = 'a' // instead of c.c = 'a'; c.c should be 'a', c.i should no longer be 3;
I tried doing as written above, but I get an error saying:
Assigning to 'data' (aka 'union Data') from incompatible type 'int'.
Is there any way to do this?
Here is an alternative approach with a tagged union and a polymorphic instantiation macro. Note however that 'a' has type int in C and char in C++, so it must be cast as (char)'a' to have type char in both languages.
#include <stdio.h>
typedef struct {
enum { CHAR, INT, FLOAT, DOUBLE } type;
union {
char c;
int i;
float f;
double d;
};
} data;
#define data(v) _Generic((v), \
char: (data){ .type = CHAR, .c = (v) }, \
int: (data){ .type = INT, .i = (v) }, \
float: (data){ .type = FLOAT, .f = (v) }, \
double: (data){ .type = DOUBLE, .d = (v) })
void print(data x) {
switch (x.type) {
case CHAR: printf("char: '%c'\n", x.c); break;
case INT: printf("int: %d\n", x.i); break;
case FLOAT: printf("float: %gf\n", (double)x.f); break;
case DOUBLE: printf("double: %g\n", x.d); break;
}
}
int main() {
data a = data((char)'a'); // char
data b = data('a'); // int
data c = data(3); // int
data d = data(1.2f); // float
data e = data(3.14); // double
print(a);
print(b);
print(c);
print(d);
print(e);
return 0;
}
Output:
char: 'a'
int: 97
int: 3
float: 1.2f
double: 3.14
No. It's not possible. If you want type switching use _Generic but 'a' is an integer character constant (i.e. type is int) so you will only find partial success with sample input provided:
#include <stdio.h>
typedef union {
char c;
double d;
float f;
int i;
} data;
#define set(d, v) _Generic((v),\
char: setc,\
double: setd,\
float: setf,\
int: seti\
)((d), (v))
void setc(data d, int v) {
d.c = v;
printf("c = %c\n", d.c);
}
void setd(data d, double v) {
d.d = v;
printf("d = %lf\n", d.d);
}
void seti(data d, int v) {
d.i = v;
printf("i = %d\n", d.i);
}
void setf(data d, float f) {
d.f = f;
printf("f = %f\n", d.f);
}
int main() {
data d = { 0 };
set(d, 'a'); // seti()
set(d, (char) 'c');
set(d, 3.14);
set(d, 1.2f);
set(d, 3);
}
and the resulting output:
i = 97
c = c
d = 3.140000
f = 1.200000
i = 3
void f(int a, char b, char* c) {
if(..) {
...
f(a,b,c); //recursive
}
...
}
void g(int a, double b, char* c, int d) {
if(..) {
...
g(a,b,c,d); //recursive
}
...
}
I want to make a separate function because I use the code within the if statement several times. But this function have to have a function as a parameter becuase I use recursive method. I know that we can use function as a parameters, but in the f function there are 3 parameters, in the g function have 4 parameters.
The code in the if statement in f is the same as the code in the if of g. Except for the function call in that code?
Simply I have no idea how to solve this issue.
You can use union to pack the variable number of arguments, as shown in sample code below.
It may be unusual to use union like this, but it works.
#include<stdio.h>
union u {
struct { int a; char b; char* c; } f;
struct { int a; double b; char* c; int d; } g;
};
void func_u_f (union u* ua) {
printf(" f = {a: %d, b: %c, c:%s}\n", ua->f.a, ua->f.b, ua->f.c);
ua->f.a++;
}
void func_u_g (union u* ua) {
printf(" g = {a: %d, b: %e, c:%s, d:%d}\n",
ua->g.a, ua->g.b, ua->g.c, ua->g.d);
ua->g.a++; ua->g.b *= 2.0; ua->g.d++;
}
void r (int i, void (*func) (union u*), union u* ua) {
if (i < 3) { /* or whatever conditions to terminate recursion */
printf ("Recursion %d\n", i);
func(ua);
r (++i, func, ua);
} else {
printf ("Exit recursion at %d\n", i);
return;
}
}
int main () {
union u u1, u2;
/* f */
u1.f.a = 10; u1.f.b = 'X'; u1.f.c = "I am u.f.";
r(0, &func_u_f, &u1);
/* g */
u2.g.a = 10; u2.g.b = .4e-6; u2.g.c = "I am u.g."; u2.g.d = 98;
r(-2, &func_u_g, &u2);
return 0;
}
I am proposing you an easy fix that doesn't work in general because it involves the use of a sentinel value.
Let's say that the the variable d that you pass to g is always positive. Than you can choose -1 as sentinel value.
You always pass four parameters to the function myIf and then check whether d is -1. If it is, then you call f with three parameters, otherwise you call g.
int main() {
myIf(a, b, c, d);
return 0;
}
void myIf(int a, int b, char *c, int d)
{
if( d == -1 ) {
f(a, b, c);
}
else {
g(a, b, c, d);
}
}
I'm not sure exactly what you're trying to do. But if you're worried about code duplication in the if statements, you can refactor that our to another function:
if (isCondition()) ...
bool isCondition() { return ... }
I'm a bit confused as to how to implement the following. I want to have a function, func2, return a function that with call func1 with the specified parameters:
int func1(int x, int y, int z, int type){
// Calculations
}
int ((*func2)(int x, int y, int z))(int type){
// Return a pointer to func1 that with get x, y, z as parameters
// when called later, with type = type being fixed
}
Use:
my_func = func2(3);
printf("result = %d\n", my_func(1,2,3));
For this to work you need something called a closure which is basically a record with the function and the type as fields. Below is an example to illustrate the idea. In a real program you also need to check that malloc doesn't return NULL, and free the memory.
#include <stdio.h>
#include <stdlib.h>
typedef struct ClosureDesc *Closure;
struct ClosureDesc {
int type;
int (*function)(Closure c, int x, int y, int z);
};
int func1(Closure c, int x, int y, int z)
{
return c->type;
}
Closure func2(int type)
{
Closure c;
c = malloc(sizeof *c);
c->type = type;
c->function = func1;
return c;
}
int main(void)
{
Closure my_func;
my_func = func2(3);
printf("result = %d\n", my_func->function(my_func, 1,2,3));
return 0;
}
Function pointers syntax is a bit confusing but you can make it easier typedefing the functions itself. Then you can use "normal" pointer syntax.
typedef int func(int,int,int);
int func1(int x, int y, int z){
// Calculations
return 1;
}
int func2(int x, int y, int z){
// Calculations
return 2;
}
int func3(int x, int y, int z){
// Calculations
return 3;
}
func *selectfunc(int type)
{
func *f = NULL;
switch(type)
{
case 1:
f = func1;
break;
case 2:
f = func2;
break;
case 3:
f = func3;
break;
}
return f;
}
int main(void)
{
int type = rand()%3;
printf("%d", selectfunc(type)(1,2,3));
}
or
func *fptr = selectfunc(2);
fptr(1,2,3);
Here’s what I think you’re going for:
int func1( int x, int y, int z )
{
...
}
/**
* func2 takes an integer parameter and returns a
* pointer to a function that takes 3 integer
* parameters and returns int
*/
int (*func2(int type))(int, int, int)
{
/**
* This example is based on what you wrote in your
* question. Regardless of how you actually select
* which function to return based on the input, the
* return statement will be the same.
*/
switch ( type )
{
case 3:
return func1;
break;
default:
break;
}
return NULL;
}
int main( void )
{
int (*my_func)(int, int, int);
...
my_func = func2( 3 );
if ( my_func )
printf( "result = %d\n", my_func( 1, 2, 3 ) );
...
}
If you write func2 such that it can never return NULL and you want your co-workers to throw things at you, you can dispense with the my_func variable and just write
printf( "result = %d\n", func2(3)(1, 2, 3));
I wouldn’t recommend it though, unless you like rude comments in code reviews.
i need get some logs from uses of variables in C code;
For example from the following code:
int main(){
int a,b,c;
a=1;
b=1;
c= a==0||b==1
return 0;
}
i make:
int log(int v){
//print log
return v;
}
int main(){
int a,b,c;
a=1;
b=1;
c= log(a)==0||log(b)==1
return 0;
}
this work perfectly, but with all variables int.
how can i do this for variable of any type?
#include <stdio.h>
#define LOG(TYPE, STRING, VAR) \
(printf(STRING, VAR), (TYPE) VAR)
int main()
{
int j = 3;
double q = 2.3;
double s;
s = LOG(int, "j=%d\n", j) + LOG(double, "q=%lf\n", q);
LOG(double, "s=%lf\n", s);
}
j=3
q=2.300000
s=5.300000
One caution: This evaluates the VAR expression twice, so it should always be the contents of a regular variable, not a more complex expression. You can replace the call to printf with a call to a logging operation that uses varargs.
Log4c is your friend:
Log4c is a library of C for flexible logging to files, syslog and other destinations. It is modeled after the Log for Java library (http://jakarta.apache.org/log4j/), staying as close to their API as is reasonable. Here is a short introduction to Log4j which describes the API, and design rationale.
how can i do this for variable of any type?
To switch code based on various types, use _Generic() to select type specific functions.
int log_int(int v) {
printf("(int %d)\n", v);
return !!v;
}
int log_double(double v) {
printf("(double %e)\n", v);
return !!v;
}
int log_char_ptr(char *v) {
printf("(str %s)\n", v);
return !!v;
}
#define mylog(X) _Generic((X), \
int: log_int, \
double: log_double, \
char *: log_char_ptr \
)(X)
Now code only needs to call mylog(various_types).
int main(void) {
int i = 3;
double d = 4.0;
char *s = "5";
mylog(i)==0||mylog(d)==0||mylog(s)==0;
return 0;
}
Output
(int 3)
(double 4.000000e+00)
(str 5)
How can I create a "function pointer" (and (for example) the function has parameters) in C?
http://www.newty.de/fpt/index.html
typedef int (*MathFunc)(int, int);
int Add (int a, int b) {
printf ("Add %d %d\n", a, b);
return a + b; }
int Subtract (int a, int b) {
printf ("Subtract %d %d\n", a, b);
return a - b; }
int Perform (int a, int b, MathFunc f) {
return f (a, b); }
int main() {
printf ("(10 + 2) - 6 = %d\n",
Perform (Perform(10, 2, Add), 6, Subtract));
return 0; }
typedef int (*funcptr)(int a, float b);
funcptr x = some_func;
int a = 3;
float b = 4.3;
x(a, b);
I found this site helpful when I was first diving into function pointers.
http://www.newty.de/fpt/index.html
First declare a function pointer:
typedef int (*Pfunct)(int x, int y);
Almost the same as a function prototype.
But now all you've created is a type of function pointer (with typedef).
So now you create a function pointer of that type:
Pfunct myFunction;
Pfunct myFunction2;
Now assign function addresses to those, and you can use them like they're functions:
int add(int a, int b){
return a + b;
}
int subtract(int a, int b){
return a - b;
}
. . .
myFunction = add;
myFunction2 = subtract;
. . .
int a = 4;
int b = 6;
printf("%d\n", myFunction(a, myFunction2(b, a)));
Function pointers are great fun.
You can also define functions that return pointers to functions:
int (*f(int x))(double y);
f is a function that takes a single int parameter and returns a pointer to a function that takes a double parameter and returns int.