What do pointers have to do with Functions

#include <iostream>
using namespace std;

int addition (int a, int b)
{ return (a+b); }

int subtraction (int a, int b)
{ return (a-b); }

int operation (int x, int y, int (*functocall)(int,int))
{
int g;
g = (*functocall)(x,y);
return (g);
}

int main ()
{
int m,n;
int (*minus)(int,int) = subtraction;

m = operation (7, 5, addition);
n = operation (20, m, minus);
cout <<n;
return 0;
}
I read the section of this but I dont understand it. Can somebody explain whats happening here?
All a function name is, is a symbolic name to the address of a block of executable code. Being a symbolic name, you make the code treat it as a variable, by the use of pointers to functions.

 
int (*functocall)(int,int)


This is a "prototype" for a function call through the use of a pointer. The * within the first parens makes it a pointer to a function. The function accepts to int arguments and returns an int.

You can assign any function that accepts two int arguments and returns an int to that pointer.

1
2
m = operation (7, 5, addition);
n = operation (20, m, minus);


This two calls pass the function names addition and minus to the function operation.

1
2
3
4
5
6
7

int operation (int x, int y, int (*functocall)(int,int))
{
int g;
g = (*functocall)(x,y);
return (g);
}


The function "operation" calls the function(keep in mind, it's an address now) functocall. Again, any function that accepts two int arguments and returns an int can be used on the "operation" call by placing its name in the call.

 
int (*minus)(int,int) = subtraction;


This section of code subs in the name of the function "subtraction" for the function name "minus," so calling "operation" with the name minus is actually passing the address of the function "subtraction."

It possible to do some really awesome stuff with pointers to functions.

Here is some of my old ansi c code using function pointers (stripped of non-essentials):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int (*readfunc[])(MDL *, char *) =
{
	file_readtri,
	file_readac3d,
	NULL
};

fmt_idx = file_findformat( &argv[i][str_idx] );

if ( !(readfunc[fmt_idx])(&mdl, argv[i]))
{
	disp_error ("File reader", __FILE__, __LINE__);
	return 0;
}


This would get the file format by getting the extension, return an index into the array of function pointers and run that reader code.

I could have, and probably should have, made it a struct, like so:

1
2
3
4
5
6
7
8
9
struct fileformat {
   int (*readfunc)(MDL *, char *);
   char extension;
} ff[] =
{ 
    file_readtri, "tri",
    file_readac3d, "ac",
    NULL
};



Last edited on
Okay Dumb it down a little because I have no idea what you just said. To be honest I still dont understand pointers very well. I know they are variables that point to different variables. I dont understand their purpose whatsoever because instead of just using them as a pathway you could just make two variables equal to eachother. But with this code to start with what is (*minus) Im so confused

Okay Dumb it down a little because I have no idea what you just said. To be honest I still dont understand pointers very well. I know they are variables that point to different variables.


No, pointers point to addresses in memory. If that address happens to be the address of a variable, then all is good.

Some elaboration:

int *x_ptr;
int x;

x_ptr = &x; // & is a reference or "address of" operator here.

x_ptr points to the address where x is located. You can access x through x_ptr by dereferencing it: y = *x_ptr * 2;

The * on x_ptr tells the compiler you want to access what is stored at the address x_ptr points to. Without the *, you are getting the address it points to.

You can do this with classes and structures (essentially public classes) just as well:

Triangle *tri_ptr;
Triangle tri;

tri_ptr = &tri;

Function names are no more than a symbolic name for the address where that function's code begins, similar to a variable name. A variable name is really nothing more than a symbolic name for an address in memory. So you can make a pointer to a function and treat it as a variable:

int addition(int a, int b);

int (*mathop)(int, int) = addition;

Assigns the address of the function addition to the "variable" mathop.

Note, that the prototype for the function to be called must match the prototype for the function pointer: two int arguments, returning an int.

Instead of assigning addition to the function pointer mathop, you can pass the function name to a function that accepts pointers to function. This is called a call back function.


m = operation (7, 5, addition);


Passes the name(address) of addition to the function "operation."

int operation (int x, int y, int (*functocall)(int,int))

Operation accepts two integers and a pointer to a function that accepts two integers and returns an int.

Operation then calls "functocall" with the two integers passed to operation and receives the integer returned by the function call. In this case, the function "addition."

If you're still not getting it, I'll try some pictures.
Last edited on
"Function names are no more than a symbolic name for the address where that function's code begins, similar to a variable name. A variable name is really nothing more than a symbolic name for an address in memory. So you can make a pointer to a function and treat it as a variable:"

I understand this now. So basically function addition and lets say x both have addresses that pointers can point to and dereference. Though I havent learned classes or any of that yet. But to be honest the reason I think I keep getting stuck on pointers is because I do not truly understand their purpose and I keep getting angry at myself for this.

                 x1                                             x2 
                +--------+--------+--------+-------+--------+--------+--------+--------+
Address    |0x00f0|0x00f2|0x00f3|0x00f4|0x00f5|0x00f6|0x00f7|0x00f8|
without *  |          |           |           |           |          |           |           |           |
                 +-------+--------+--------+--------+-------+--------+--------+--------+
Contents   |                                              |                                               |
with *        |    40569382                          |  75739204                             |
                 +-------+--------+--------+--------+-------+--------+--------+--------


Bear with this picture, I don't know how to format for this forum system.

Pointers:

X1 and x2 are both allocated as ints (32 bit system, four bytes each) at the address locations 0x00f0 and 0x00f5 respectively and assigned 40569382 and 75739204 respectively.

int *x_ptr = &x1;

x_ptr points to address 0x00f0.
*x_ptr points at(contains) 40569382.

Reassigning x_ptr:

*x_ptr = &x2;

x_ptr now points to address 0x00f5
*x_ptr now points at(contains) 75739204

It's similar with functions. They are placed at an address and you can point to them. Since I can't seem to get formatting right, it might be best to look for help elsewhere.
Last edited on
No this is great I understand it now. But everywhere I'm reading online it says arrays and pointers are very alike. how so? I know that if you have, lets say int array[10], you would have one variable (array) that has 40 bytes of memory set aside for itself to contain. and if you have a pointer int* x=&array x will point to the first memory address of array. So the first address of the first element.
Its nice to actually begin to understand the information behind the words.

No this is great I understand it now. But everywhere I'm reading online it says arrays and pointers are very alike. how so?


Not entirely so.


I know that if you have, lets say int array[10], you would have one variable (array) that has 40 bytes of memory set aside for itself to contain. and if you have a pointer int* x=&array x will point to the first memory address of array. So the first address of the first element.


Yes, but using a pointer, you would access individual elements by pointer arithmetic. A pointer has two aspects to it: what it point to and the size of the element it points to.

Something to make it clearer:

char chararray[40];
int intarray[10];

Both are 40 bytes long.

char *char_ptr = chararray;
int *int_ptr = intarray;

Without the subscripting of the two arrays, you're getting a reference to the start of them. Both pointers point at the zeroth element and if you dreferenced the pointers:

char ch = *char_ptr;
int i = *int_ptr;

you're getting the first element.

You can use the pointer to move through the array using normal arithmetic:

char_ptr += 5;
int_ptr++;

char ptr now points at the sixth element in char_array or char_array[5], five bytes past the beginning and
int_ptr points to the second element of int_array or int_array[1], four bytes past the beginning.

Pointers are mobile and move in accordance to their size, arrays are static. Going back to a previous example:


char *char_ptr = chararray;
int *int_ptr = intarray;

You could pass char_ptr or char_array to a function and they would essentially work alike. Same for int_ptr and intarray. However, this is where it gets dangerous, there is no bounds checking.

I have an error in my post above:



Reassigning x_ptr:

*x_ptr = &x2;


That should be x_ptr = &x2.

Remember, * accesses what you're pointing at. *x_ptr = &x2 would store the address of x2 to the memory address x_ptr points at, but would not move it to point to x2.


Last edited on
Topic archived. No new replies allowed.