Explain function pointer in C [duplicate] - c

This question already has answers here:
How do function pointers in C work?
(12 answers)
Closed 8 years ago.
How is the most basic function pointer created in C?

Here's a pretty straightforward example:
#include <stdio.h>
#include <string.h>
int add(int x, int y) {
return x + y;
}
int sub(int x, int y) {
return x - y;
}
int main() {
char const * operator = "addition";
int (*operation)(int, int) = NULL;
if (strcmp(operator, "subtract") == 0)
operation = sub;
if (strcmp(operator, "addition") == 0)
operation = add;
if (operation) {
int x = 3;
int y = 7;
int z = operation(x, y);
printf("%s %d %d == %d\n", operator, x, y, z);
}
}
Where is this useful?
A common use case that I've seen is to create interfaces. So, for example, we have a type of object, say a struct that represents a network interface. Now, because there are different hardware backend, we might want to implement the functions differently depending on the hardware implementation.
So we might have a function pointer in the interface struct for initializing the hardware, sending packets, and receiving packets.

This code will demonstrate how to create and modify a basic function pointer
#include <stdio.h>
int my_function(int);
int (*function)(int)=&my_function;
int my_function2(int x){
function=&my_function; // & is optional
return (0);
}
int my_function(int x){
function=my_function2;
return (x);
}
/* And an example call */
int main(){
printf ("%d \n",function(10));
printf ("%d \n",function(10));
printf ("%d \n",function(8));
return 0;
}

Related

What is the difference between using/not using return in a subprogram?

The second piece of code is not giving the correct value as it only passes the value of r from what I see. However, I would like to make this code work without using return (just for learning how to do it in this other way). Also, what is considered best practice between these two options? Thank you! :-)
#include <stdio.h>
#define PI 3.1416
float area(float r);
int main(void)
{
float r = 10;
printf("Area: %.2f", area(r));
return 0;
}
float area(float r) {
return PI * r * r;
}
#include <stdio.h>
#define PI 3.1416
float area(float r);
int main(void)
{
float r = 10;
printf("Area: %.2f", area(r));
return 0;
}
float area(float r) {
PI * r * r;
}
I would like to make this code work without using return (just for learning how to do it in this other way).
Using return is the only way to actually return a value from a function.
However, the C syntax provides two alternative options:
It is possible to pass another pointer as argument to the function, which points to an object in the caller, in which you then assign the value of the expression.
For example:
#include <stdio.h>
#define PI 3.1416
void area(float r, float *p);
int main(void)
{
float r = 10;
float s;
area(r, &s);
printf("Area: %.2f", s);
return 0;
}
void area(float r, float* p) {
*p = PI * r * r;
return;
}
It is also possible to define a global object and assign the value of the expression to that global object instead.
For example:
#include <stdio.h>
#define PI 3.1416
float s;
void area(float r);
int main(void)
{
float r = 10;
area(r);
printf("Area: %.2f", s);
return 0;
}
void area(float r) {
s = PI * r * r;
return;
}
But that is considered to be bad practice because the connections from and to the function and with that the actual use of the function are then much harder to understand than using parameters and return types, which on the other hand show the relation and the use of the particular function call pretty good.
The use of global objects shall be avoided if possible although there are cases where a global objects is suitable, if you f.e. use an object in multiple functions and the role of the object is exactly defined. But in the provided example of yours, a global object does not fit very well and shall be avoided.
If no value shall be returned, define the return type of the function as of type void.

how can I return values of any type in C?

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 to print cascaded names of functions pointers?

I was working of functions pointers examples and I developed 4 simple functions and assigned them to a function pointer array, then I ran the code and worked for the 4 functions, but then I thought to also print the names of the functions.
I learned about __func__ and it only prints the name of the current function, so is there anyway to assign __func__ to the function pointer or another method to print the names of the functions?
This is the example I'm working on right now:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
int add(int x, int y);
int sub(int x, int y);
int mul(int x, int y);
int divide(int x, int y);
int main() {
int m = 6;
int n = 10;
int res,i;
int (*fun[4])(int,int)={add,sub,mul,divide};
for (i=0;i<4;i++)
{
printf("result of %s operation\n",__func__=fun[i]);
}
}
int add(int x, int y) {
int result = x + y;
return result;
}
int sub(int x, int y) {
int result = x - y;
return result;
}
int mul(int x, int y) {
int result = x * y;
return result;
}
int divide(int x, int y) {
int result = x / y;
return result;
}
As you can see I'm trying to assign the __func__ to the functions pointer but of course it's not working.
The __func__ constant in every function is only accessible in runtime. Meaning that if you want to use that one, you have to grab it while calling the function. Like this:
typedef int calc_func_t (int x, int y, const char** func);
int add(int x, int y, const char** func);
...
calc_func_t* fun[4] = {add,sub,mul,divide};
for (i=0;i<4;i++)
{
const char* func;
int result = fun[i](1,1,&func);
printf("result of %s operation %d\n", func, result);
}
...
int add(int x, int y, const char** func)
{
int result = x + y;
*func = __func__;
return result;
}
...
If you wish to know what the functions are named at compile-time and then later on use that information, the easiest and best way would be to create a look-up table:
typedef struct
{
calc_func_t* func;
const char* name;
} calc_func_info_t;
const calc_func_info_t func_info [] =
{
{add, "add"},
{sub, "sub"},
...
};
Compiled code doesn't contain functions and symols names by default. You can use some macros to create constant strings containing functions names to be included in the compiled binary:
#include <stdio.h>
// function call type
typedef void fn_call();
// record describing one function
typedef struct fn_record {
const char *name; // function's name as a constant string
fn_call *call; // function call
} fn_record;
// the functions to be called and named
void fna() { printf("called fna\n"); }
void fnb() { printf("called fnb\n"); }
void fnc() { printf("called fnc\n"); }
// macro, that generates record for each function, it creates
// string like { "fna", fna } to save You typing
#define FN_RECORD(f) { #f, f }
// now define array of functions records
fn_record fns[3] = {
FN_RECORD(fna),
FN_RECORD(fnb),
FN_RECORD(fnc)
};
// ... which becomes:
// fn_record fns[3] = {
// { "fna", fna },
// { "fnb", fnb },
// { "fnc", fnc }
// };
int main(void) {
int i;
// ... use it whatever You like
for (i = 0; i < 3; i++) {
printf("%s\n", fns[i].name);
fns[i].call();
}
return 0;
}
Basically, there is no way.
// A function declaration
void MyFunction(void);
// a pointer to the function
void (*fnPointer)(void) = MyFunction;
// No way to retrieve function name "MyFunction" from fnPointer
Ofcourse, if you have a known set of possible functions that might be assigned to the pointer, you could compare them explicitely.
Also, you can change the stored function pointer to be combined with the function name. Could be something similar to the following:
struct FunctionPointerContainer
{
void (*fnPointer)(void);
char* fnName;
};
#define MakeFunctionPointer(fn) FunctionPointerContainer { fn, #fn }
// later
struct FunctionPointerContainer myPointer = MakeFunctionPointer(MyFunction);
myPointer.fnPointer(); // call
myPointer.fnName; // the function name
I was working of functions pointers examples
So, as I understand, your example is done for educational purposes, aren't you? In that case I would do it as simple as it can be to not confuse the students who use your example to learn how function pointers work.
I learned about __func__ and it only prints the name of the current function
Despite other answers show very nice and smart solutions how to have the function name outside of it, from the perspective of simplicity I would still use the __func__ as it normally works, inside the called function:
#include <stdio.h>
#define print_info(format, ...) \
printf("Function '%s' is called with parameters: "format"\n", \
__func__, __VA_ARGS__)
int add(int x, int y);
int sub(int x, int y);
int mul(int x, int y);
int divide(int x, int y);
int main() {
int m = 6, n = 10, i;
int (*fun[4])(int,int) = { add, sub, mul, divide };
for (i = 0; i < 4; ++i)
printf("-- result is: %d\n", fun[i](n, m));
return 0;
}
int add(int x, int y) {
print_info("%d, %d", x, y);
return x + y;
}
int sub(int x, int y) {
print_info("%d, %d", x, y);
return x - y;
}
int mul(int x, int y) {
print_info("%d, %d", x, y);
return x * y;
}
int divide(int x, int y) {
print_info("%d, %d", x, y);
return x / y;
}

Conflicting types error in compiler

My issue is that I keep getting the same type of error and I can not understand why. I'm fairly sure I declared and defined it before the main function.
Here is my code.
#include <stdio.h>
void functn (int x);
int functn(int x, int result){
result = (x-1)+2;
if (x <= 0){
return 0;
}
else{
return result;
}
}
int main (){
int x, y;
printf ("Enter the value of x: ");
scanf ("%d", &x);
y = f(x);
printf ("%d", y);
return 0;
}
You have a number of problems in functn. Primarily passing result. When you pass result to functn, functn receives a copy of result and the only way to get the modified value is to return the modified value. You can also pass a pointer to result and update *result in functn (similar to what you do now), that would eliminate the need to return a value, as any changes to result would be visible back in the calling function (main() here). Further, there is no need for global variables. Simply declare the variables local to main and pass as parameters, as required.
The following example declares functn (simply f below) to do both, take a pointer to result (e.g. &result) as a parameter, while also returning result, which allows you to either assign the return or not, but always have the updated value for result back in main, e.g.
#include <stdio.h>
int f (int x, int *result);
int main (void){
int x, y, result = 0;
printf ("Enter the value of x: ");
if (scanf ("%d", &x) != 1) {
fprintf (stderr, "error scanf, invalid conversion.\n");
return 1;
}
y = f (x, &result);
printf ("y = f(%d) => %d\n", x, y);
return 0;
}
int f (int x, int *result)
{
*result = (x-1)+2;
if (x <= 0)
return 0;
return *result;
}
Example Use/Output
$ ./bin/yfx
Enter the value of x: 5
y = f(5) => 6
Look things over and let me know if you have questions.
Return type of functn() different in declaration and definition. So, use
int functn(int x);
instead of
int functn(int x, int result)
Remove int result from function argument and declare inside function. like,
int functn(int x)
{
int result = 0;
result = (x-1)+2;
if (x <= 0){
return 0;
}
else{
return result;
}
}
Also, correct function call, like
y = functn(x);
instead of
y = f(x);

Swapping variables with a function doesn't affect the call site

A few lessons ago I learned about variables, and got a question in my homework about swapping two numbers - I used a third variable to solve this question.
The solution looked somewhat like this:
#include <stdio.h>
int main(void) {
int x, y;
scanf("%d %d", &x, &y);
// swappring the values
int temp = x;
x = y;
y = temp;
printf("X is now %d and Y is now %d", x, y);
}
Now I'm learning about functions, and I wanted to try and solve the previous question with a helper swap function.
This is the code I've written:
#include <stdio.h>
void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
}
int main(void) {
int a = 3, b = 4;
swap(a, b);
printf("%d %d\n", a, b);
}
I don't know why, but the output is still 3 4 even though I changed the value inside the swap() function.
Why is this happening?
Pass address of x and y as arguments to function. Right now they are local variables, changes are not made to original variables .
Do as follows-
void swap(int *x,int *y){
/* dereference pointers and swap */
int temp = *x;
*x = *y;
*y = temp;
}
And call in main like this -
swap(&x,&y);
What you are doing is passing parameter by value. It means that during the function call, copies of parameters are created. So inside the function you are working on copies of actual variables.
Instead you need to pass it as a reference. Please read more about pass-by-value vs pass-by-reference.
#include <stdio.h>
void swap(int& x,int& y) //Instead of passing by value just pass by reference
{
int temp=x;
x=y;
t=yemp;
}
int main() {
int a=3,b=4;
swap(a,b);
printf("%d %d\n",a,b);
return 0;
}
EDIT:
C does not have references. Above code will work in c++ instead. To make in work in C, just use pointers and de-reference it inside the function.

Resources