What are Function Pointers Ponting To? - c++

Consider the following code and output:
#include <iostream>
int Add(int a, int b) {
return a + b;
}
int Subtract(int a, int b) {
return a - b;
}
int main() {
int (*fn1)(int, int);
int (*fn2)(int, int);
fn1 = &Add;
fn2 = &Subtract;
std::cout << "fn1 = " << fn1 << "\n";
std::cout << "*fn1 = " << *fn1 << "\n";
std::cout << "fn2 = " << fn2 << "\n";
std::cout << "*fn2 = " << *fn2 << "\n";
}
Output:
fn1 = 1
*fn1 = 1
fn2 = 1
*fn2 = 1
As a pointer, I would expect fn1 and fn2 to be memory addresses, and I don't really know what to expect for *fn1 and *fn2. According to Wikipedia, "a function pointer points to executable code within memory", but I don't see how "executable code within memory" corresponds with "1".

*fn1 is a function lvalue, and such a value decays to a pointer to that function in most circumstances, including when passed as a function call argument.
You can dereference the result of the decay to get another function lvalue, ad infinitum: *****fn1, ***********fn1, etc.

What are Function Pointers Ponting To?
It depends on what kind of function pointer it is. For non-member function pointer (as in your example), the pointer usually points to the actual code for the function (though on some architectures, such as PowerPC, it may point into a special "function descriptor" instead):
To examine that value, you should print it as void *, and not as bool (which is what you have done in your example).
std::cout << "fn1 = " << (void*)fn1 << std::endl;
Another way to examine it is using a debugger. For example, in GDB:
(gdb) p/a fn1
(gdb) p/a fn2

Related

The actual and formal parameters of the array use the same block address, while the variables use different addresses

When using the address transfer of function, View address blocks of formal parameters and actual parameters, I find that the arguments and formal parameters of array share one address block, while the arguments and formal parameters of variables use two address block. What is the reason?
The code is as follows:
#include<iostream>
using namespace std;
void test(int *i,int * arr) {
cout << &i << endl;
cout << arr << endl;
}
int main() {
int i = 1, arr[2] = {1,2};
cout << &i << endl;
test(&i, arr);
cout << arr << endl;
system("pause");
return 0;
}
And this is the output:
0000008986B6FC54
0000008986B6FC30
0000008986B6FC78 //Arrays use the same space
0000008986B6FC78
You are passing pointers to the functions. The value of the pointers are not modified, ie in the function they point to the same objects as they do in main.
However, you are not printing what you think you print:
void test(int *i,int * arr) {
cout << &i << endl;
cout << arr << endl;
}
The pointer i gets the parameter &i (the i from main). Hence printing i in main will yield the same value as printing i in test. However, you are printing the adress of i in the function not the value of it. If you change your code to:
void test(int *i,int * arr) {
cout << &i << endl;
cout << i << endl;
cout << arr << endl;
}
You will notice the difference. I suggest you to rename at least one of the is in your code, because using same name for different entities can and does cause confusion. The i in test holds the value of the address of the i in main. That does not mean that they are the same, but rather i in test has the same value as &i in main.
In short: &i == &i but you expect &(&i) to be the same as &i.
There is no difference between passing a pointer to the int or passing a pointer to the first element of the array. From the point of view of the function they are both just pointers to int.
Note that test prints the value of arr but the location of i.
In test, &i is the location of its argument i.
That argument's value is the location of the i in main.
You will see this if you print i instead of &i.
arr, on the other hand, is implicitly converted into a pointer to its first element, and you are both passing &arr[0] to test to print, and printing &arr[0] in main.
Here is the same thing with explicit conversions and without using a function:
int main() {
int i = 1, arr[2] = {1,2};
cout << &i << endl;
// Create the "argument"...
int *p = &i;
// These two lines are 'test'...
cout << &p << endl;
cout << &arr[0] << endl;
// and this is after the function call.
cout << &arr[0] << endl;
}

Changing the address of a pointer to edit its value

recently we were trying to use pointer to void, by passing a copy of its address to an instance of a class, in order for the instance to allocate it to the same memory space as an OpenCV Mat it contains, and that is contained in a stack of memory shared by the GPU and CPU to compute it with OpenCV+CUDA.
However while doing that we ran into an issue we didn't quite understand. When passing the address of the pointer to the object, we tried to edit that address so that the pointer was hosted on another space. And while that worked once that copy ran out of scope the value of that pointer returned to being what it was (I'll add a code snip since its confusing to even explain it). However if we accessed the content of the pointer's address that we passed to the function, and edit that, the original pointer is edited.
My hypothesis is that when we passed the pointer's address to the function a copy of the value of that memory address is made, and if that pointer to pointer is edited, the content of it is left undisturbed, while on the other function we accessed the content and directly edited it, hence the copy is left undisturbed and runs out of scope, while the content is edited correctly.
Here is a snip of the code where I try both things:
// Example program
#include <iostream>
#include <string>
void change_value(int **p, int *addr)
{
*p = addr;
}
void change_direction(int **p, int *addr)
{
std::cout << "p value: " << p << std::endl;
std::cout << "p contains: " << *p << std::endl;
std::cout << "p contains contains: " << **p << std::endl;
p = &addr;
std::cout << "p value: " << p << std::endl;
std::cout << "p contains: " << *p << std::endl;
std::cout << "p contains contains: " << **p << std::endl;
}
int main()
{
int a = 1, b = 2, c = 3;
int *ptr = &a;
std::cout << "ptr direction: " << &ptr << std::endl;
std::cout << "ptr value: " << ptr << std::endl;
std::cout << "ptr contains: " << *ptr << std::endl;
std::cout << std::endl;
change_value(&ptr, &b);
std::cout << "change_value" << std::endl;
std::cout << "ptr direction: " << &ptr << std::endl;
std::cout << "ptr value: " << ptr << std::endl;
std::cout << "ptr contains: " << *ptr << std::endl;
std::cout << std::endl;
change_direction(&ptr, &c);
std::cout << std::endl;
std::cout << "change_direction" << std::endl;
std::cout << "ptr direction: " << &ptr << std::endl;
std::cout << "ptr value: " << ptr << std::endl;
std::cout << "ptr contains: " << *ptr << std::endl;
}
This is the output we got. We can see that while ptr is edited on change_value function, since we access to the content of p and edit it, it is not changed on change_direction, since the moment we edit p's address it stops pointing to ptr.
ptr direction: 0x710a27e3fe18
ptr value: 0x710a27e3fe0c
ptr contains: 1
change_value
ptr direction: 0x710a27e3fe18
ptr value: 0x710a27e3fe10
ptr contains: 2
p value: 0x710a27e3fe18
p contains: 0x710a27e3fe10
p contains contains: 2
p value: 0x710a27e3fdd8
p contains: 0x710a27e3fe14
p contains contains: 3
change_direction
ptr direction: 0x710a27e3fe18
ptr value: 0x710a27e3fe10
ptr contains: 2
If anyone could offer a better explanation of what happened I'd be most grateful.
Cheers.
Not sure if I understand the question, but if this:
void change_direction(int **p, int *addr)
{
// ...
p = &addr;
// ...
}
Is supposed to modify the parameter passed to the function, then it isnt correct.
Parameters are passed by value unless you pass them by reference. Passing references is recommended, but if you like you can use pointers. However, then you need to modify what the pointer points to, not the pointer. In the function above p is local to the function. Modifying the value of p has no effect outside the function.
You probably want:
void change_direction(int **p, int *addr)
{
// ...
*p = addr;
// ...
}
Or rather
void change_direction(int *&p, int *addr)
{
// ...
p = addr; // p is a reference, hence no dereference needed
// ...
}
Actually you should prefer int*& here, because a nullptr is not a valid paramter (and thats about the only reason you would use a pointer rather than a reference).
#463035818_is_not_a_number offered a good answer that works well.
But there might be value in fully understanding what your original code is doing.
Beggining from the start:
int a = 1, b = 2, c = 3;
int *ptr = &a;
This initializes three pieces of memory in stack memory containing the int values you gave (a,b,c) and one more piece of memory for your ptr variable that holds the address of a.
You then print out the address and the values of ptr, which obviously doesn't change any of the values.
Next is the call to change_value(int **p, int *addr) which executes.
*p = addr;
The parameter p in this case holds an address to an address to an int somewhere in memory, so *p is the address pointed to by p.
Setting that to addr changes the address p points to.
So in your specific code:
change_value(&ptr,&b);
Sets the value of ptr to be the address of b.
Then next is the change_direction(int **p, int* addr) call (which probably should be named change_address), which executes (ignoring the printing):
p = &addr;
This sets the parameter p to be the address of addr.
But since in C/C++ all functions are called by value (in C there arent even any references, in C++ you have to specify it as #463035818_is_not_a_number mentioned), this doesnt do anything to the original values, that the function has been called with.
So the call:
change_direction(&ptr,&c)
Does not actually change what is held in ptr. At the beginning of the call to the function, the address of ptr (so &ptr) gets copied into a piece of stack-memory, which is then used in the function and freed after the function exits.
I hope this clears things up, pointers can be hard to wrap your head around sometimes.
Cheers.

Can any primitive type be passed into a function expecting a pointer?

Basically I'm wondering what the rules are for passing in pointers vs references to functions in C++. I couldn't find them stated anywhere. Can you pass a primitive type integer, for example, into a function expecting a pointer? Can't you only pass in pointers to methods expecting pointers?
A pointer is just a memory address and in c++ you can get the address of a variable by using the &. Here is an example
#include <iostream>
void increment(int& x)
{
++x;
}
void increment2(int* x)
{
++(*x);
}
int main()
{
int i = 1;
int * p = new int(1);
increment2(&i);
increment2(p);
std::cout << i << std::endl;
std::cout << *p << std::endl;
increment(i);
increment(*p);
std::cout << i << std::endl;
std::cout << *p << std::endl;
}
output
2
2
3
3
try it:
https://godbolt.org/z/br9APq

calling function depending on index of array array of functions' names

making random actions in a game makes it really look like real...
so if a character has many capabilities like move, work, study... so in programming a function of those is called depending on some conditions. what we want is a more random and real-looking like action where no condition is there but depending on a random condition the character takes a random actions..
I thought to make actions (functions) in an array then declare a pointer to function and the program can randomly generate an index which on which the pointer to function will be assigned the corresponding function name from the array:
#include <iostream>
void Foo() { std::cout << "Foo" << std::endl; }
void Bar() { std::cout << "Bar" << std::endl; }
void FooBar(){ std::cout << "FooBar" << std::endl; }
void Baz() { std::cout << "Baz" << std::endl; }
void FooBaz(){ std::cout << "FooBaz" << std::endl; }
int main()
{
void (*pFunc)();
void* pvArray[5] = {(void*)Foo, (void*)Bar, (void*)FooBar, (void*)Baz, (void*)FooBaz};
int choice;
std::cout << "Which function: ";
std::cin >> choice;
std::cout << std::endl;
// or random index: choice = rand() % 5;
pFunc = (void(*)())pvArray[choice];
(*pFunc)();
// or iteratley call them all:
std::cout << "calling functions iteraely:" << std::endl;
for(int i(0); i < 5; i++)
{
pFunc = (void(*)())pvArray[i];
(*pFunc)();
}
std::cout << std::endl;
return 0;
}
the program works fine but I only is it good or there's an alternative. every comment is welcome
There is absolutely no point in converting function pointers to void* and back. Define an array of function pointers, and use it as a normal array. The syntax for the declaration is described in this Q&A (it is for C, but the syntax remains the same in C++). The syntax for the call is a straightforward () application after the indexer [].
void (*pFunc[])() = {Foo, Bar, FooBar, Baz, FooBaz};
...
pFunc[choice]();
Demo.
Note: Although function pointers work in C++, a more flexible approach is to use std::function objects instead.

c++ pointer to function not changed

I have defined some functions and I print their address like this:
#include<iostream>
#include <string>
using std::cout;
std::string func()
{
return "hello world\n";
}
int func2(int n)
{
if (n==0)
{
cout << func2 << std::endl;
return 1;
}
cout << func2 << std::endl;
return n + func2(n - 1);
}
//================================================
int main()
{
int (*fun)(int) = func2;
cout << fun;
cout << std::endl << func2(3);
}
When I print the function's name (address) they all print 1 on my compiler (Mingw gcc 4.8 ).
Is it OK or it should differ?
It doesn't exist an overload of operator<< for std::ostream that takes a function pointer. Thus the operator<<(std::ostream&, bool) overload is prefered. The address of a function is always evaluated to true when converted to bool. Thus, 1 is printed.
Alternatevely, if a function pointer is not larger than the size of a data pointer, you could cast your function pointer to a void* via reinterpret_cast and evoke the operator<<(std::ostream&, void*) overload and thus get the actual address of the function printed.
int (*fun)(int) = func2;
std::cout << reinterpret_cast<void*>(fun) << std::endl;
Live Demo
However, as correctly Neil and M.M mentioned in the comments there's no standard conversion from a function pointer to a data pointer, and this could evoke undefined behaviour.
Alternatively, and in my humble opinion properly, you could format your function pointer as a char array buffer and convert its address to a string in the following way:
unsigned char *p = reinterpret_cast<unsigned char*>(&func2);
std::stringstream ss;
ss << std::hex << std::setfill('0');
for(int i(sizeof(func2) - 1); i >= 0; --i) ss << std::setw(2)
<< static_cast<unsigned int>(p[i]);
std::cout << ss.str() << std::endl;
Live Demo
You're not printing the address because it's now converted to a boolean value.
But you can do e.g. this:
std::cout << reinterpret_cast<unsigned long long int *>(func2) << std::endl;
Now you'll get the actual address.