Pointers looking like function pointers - c++

As I starting to learn C++, this question may be stupid but I do not understand some strange pointers.
void (*p1(int*))(float*);
int* (*(*p2)(double(*fp1)(char), int*))(float *);
int* (*(*p3)(double(*)(char), int*))(double*);
I think p2 and p3 are function pointers pointing to a function that returns a pointer to int but I am totally lost about the rest.
Also I don't understand p1 at all.
Can anyone help me please?
Thanks.

Because of p1(int*) we know that p1 is a function taking argument int*. The return type of the function is the rest of the declaration once we delete the part we already analyzed, void (*)(float*) (i.e. pointer to function taking float * and returning void.
p2 and p3 have the same form, just p2 gives a name to the function parameter. So I will only address one of them, p3.
Because of (*p3)(double(*)(char), int *) we know that (*p3) is a function taking arguments double(*)(char) and int *. The return type of the function is the rest of the declaration without the part we already analyzed, i.e. int*(*)(double *). Since (*p3) has that function type, then p3's type is: pointer to that function.

p1 is a function that returns a pointer to a function. You are correct about p2. It is a pointer to a function that takes two arguments - a pointer to a function and a pointer to an int - and returns a pointer to a function. p3 is the same.

Related

What's the difference between * and & in C?

I'm learning C and I'm still not sure if I understood the difference between & and * yet.
Allow me to try to explain it:
int a; // Declares a variable
int *b; // Declares a pointer
int &c; // Not possible
a = 10;
b = &a; // b gets the address of a
*b = 20; // a now has the value 20
I got these, but then it becomes confusing.
void funct(int a) // A declaration of a function, a is declared
void funct(int *a) // a is declared as a pointer
void funct(int &a) // a now receives only pointers (address)
funct(a) // Creates a copy of a
funct(*a) // Uses a pointer, can create a pointer of a pointer in some cases
funct(&a) // Sends an address of a pointer
So, both funct(*a) and funct(&a) are correct, right? What's the difference?
* and & as type modifiers
int i declares an int.
int* p declares a pointer to an int.
int& r = i declares a reference to an int, and initializes it to refer to i.
C++ only. Note that references must be assigned at initialization, therefore int& r; is not possible.
Similarly:
void foo(int i) declares a function taking an int (by value, i.e. as a copy).
void foo(int* p) declares a function taking a pointer to an int.
void foo(int& r) declares a function taking an int by reference. (C++ only)
* and & as operators
foo(i) calls foo(int). The parameter is passed as a copy.
foo(*p) dereferences the int pointer p and calls foo(int) with the int pointed to by p.
foo(&i) takes the address of the int i and calls foo(int*) with that address.
(tl;dr) So in conclusion, depending on the context:
* can be either the dereference operator or part of the pointer declaration syntax.
& can be either the address-of operator or (in C++) part of the reference declaration syntax.
Note that * may also be the multiplication operator, and & may also be the bitwise AND operator.
funct(int a)
Creates a copy of a
funct(int* a)
Takes a pointer to an int as input. But makes a copy of the pointer.
funct(int& a)
Takes an int, but by reference. a is now the exact same int that was given. Not a copy. Not a pointer.
void funct(int &a) declares a function that takes a reference. A reference is conceptually a pointer in that the function can modify the variable that's passed in, but is syntactically used like a value (so you don't have to de-reference it all the time to use it).
Originally in C there were pointers and no references. Very often though we just want to access a value without copying it and the fact that we're passing around an address and not the actual value is an unimportant detail.
C++ introduced references to abstract away the plumbing of pointers. If you want to "show" a value to a function in C++ then references are preferable. The function is guaranteed that a reference is not null and can access it as if it were the value itself. Pointers are still necessary for other purposes, for example, you can "re-aim" a pointer or delete with a pointer but you can't do so with a reference.
Their functionality does overlap and without a bit of history it should confuse you that we have both.
So the answer to your direct question is that very often there is no difference. That said, f(int*) can be useful if you want the function to be able to check if the pointer is null. If you're using C then pointers are the only option.
The meaning of * is dependent on context. When in a data or function argument declaration, it is a datatype qualifier, not an operator int* is a datatype in itself. For this reason it is useful perhaps to write:
int* x ;
rather than:
int *x ;
They are identical, but the first form emphasises that it the * is part of the type name, and visually distinguishes it from usage as dereference operator.
When applied to an instantiated pointer variable, it is the dereference operator, and yields the the value pointed to.
& in C is only an operator, it yields the address (or pointer to) of an object. It cannot be used in a declaration. In C++ it is a type qualifier for a reference which is similar to a pointer but has more restrictive behaviour and is therefore often safer.
Your suggestion in the comment here:
funct(&a) // Sends an address of a pointer
is not correct. The address of a is passed; that would only be "address of a pointer" is a itself is a pointer. A pointer is an address. The type of an address of a pointer to int would be int** (a pointer to a pointer).
Perhaps it is necessary to explain the fundamentals of pointer and value variables? A pointer describes the location in memory of a variable, while a value describes the content of a memory location.
<typename>* is a pointer-to-<typename> data type.
&*<value-variable> yields the address or location of <variable> (i.e. a pointer to <variable>),
**<pointer-variable> dereferences a pointer to yield the the value at the address represented by the pointer.
So given for example:
int a = 10 ;
int* pa = &a ;
then
*pa == 10
When you do func(&a) that's called a "call by reference" that means your parameter "a" can actually be modified within the function and any changes made will be visible to the calling program.
This is a useful way if you want to return multiple values from a function for example:
int twoValues(int &x)
{
int y = x * 2;
x = x + 10;
return y;
}
now if you call this function from your main program like this:
int A, B;
B = 5;
A = twoValues(B);
This will result in:
A holding the value 10 (which is 5 * 2)
and B will hold the value 15 (which is 5 + 10).
If you didn't have the & sign in the function signature, any changes you make to the parameter passed to the function "twoValues" would only be visible inside that function but as far as the calling program (e.g. main) is concerned, they will be the same.
Now calling a function with a pointer parameter is most useful when you want to pass an array of values or a list. Example:
float average ( int *list, int size_of_list)
{
float sum = 0;
for(int i = 0; i < size_of_list; i++)
{
sum += list[i];
}
return (sum/size_of_list);
}
note that the size_of_list parameter is simply the number of elements in the array you are passing (not size in bytes).
I hope this helps.
C++ is different from c in many aspects and references is a part of it.
In terms of c++ context:
void funct(int *a) // a is declared as a pointer
This corelates to the use of pointers in c..so, you can compare this feature to that of c.
void funct(int &a) // a now receives only pointers (address)
This would lead to the reference usage in c++...
you cannot corelate this to that of c..
Here is a good q&a clarifying differences between these two.
What are the differences between a pointer variable and a reference variable in C++?

On C++ pointers and references, clarification needed

What of the below is wrong please?
It is my understanding that a pointer represents an address of something of some type.
So, int i = 18, a pointer to it is int *pI = &i;
The following 2 declarations are valid
void foo (int &something) // Will accept an address of something
void bar (int *something) // Will accept a pointer to something
When we declare a function as
void bar (int *something)
We better send a pointer to something. Indeed, foo(pI) works.
Following the same logic, when looking at
void foo (int &something)
We should send it an address of something pointing to an int as an argument, so then:
Why is foo(&i) wrong?
void foo (int &something) // Will accept an address of something
This is incorrect: int& is a reference, a concept that is similar to pointers in certain ways, but not at all identical.
References are similar to pointers in that a value can be changed through a reference, just like it can be changed through a pointer. However, there is no such thing as "null reference", while NULL pointers are very common.
When you call a function that takes a reference, you simply pass the variable the reference to which you are taking - no & operator is required:
void foo (something); // "something" must be a variable
The declaration void foo (int &something) takes a reference variable, not a pointer.
You call it exactly the same as you would call void foo (int something), except that something is passed by reference, not by value.
void foo (int &something) // Will accept an address of something
No, though I can understand the confusion. That function takes a reference to int. References are guaranteed to be non-null in a well defined program. It is similar conceptually to a pointer, but semantically different.
To call that function you don't need to do anything special.
int i = 10;
foo(i); // passed to foo by reference
Because in C++ the & means "reference type" in the context of a function prototype as you are using it here. Your function:
void foo (int &something)
is actually specifying that an integer reference type should be passed, so you would simply call this function like this:
foo(i);
Note that in this case you are still passing the address of i into the function, but you are doing it as a reference type rather than a raw pointer.
There are two different meanings for &.
The first is to create a pointer from an existing variable.
The second is to make a reference.
Even though they both use the same character, they are two completely different things.

C++ pointers to functions as param

#include<iostream>
using namespace std;
void passPointer(int *pointer)
{
cout << *pointer;
}
int main()
{
int *iNum = new int(25);
passPointer(iNum);
return 0;
}
Can someone explain to me why when I use the passPointer() function in main, it has to be passPointer(iNum) but not passPointer(*iNum)? Is it because I am dereferencing it at the parameter if I use *? Please explain as detailed as you can as I am a bit confused.
Thanks guys.
It is because you have declared passPointer to take an argument of
type int*. iNum has type int*, and so can be passed directly to
passPointer. *iNum has type int, and there is no implicit
conversion of int to int*, so you can't pass it to passPointer.
More generally, in C++ (and in just about all other typed languages as
well), every expression and every variable has a type. The type of an
expression is expressed in terms of the type of its operands: if the
type of the operand of a unary * is T* (and the type must be a
pointer), then the type of the results is T. And to call a function,
you must provide the right number of arguments, with the right types.
I am very sympathetic to these sorts of questions, because this is one of the only things that I had trouble with when learning C++.
The basic problem is that in the syntax of C++, the * and & characters are used for many different things with similar but subtly different meanings.
In your case, you are considering using * in four different places.
In the first place: int *iNum = new int(25);, the * is sitting in a declaration. This means that is is a type annotation saying that iNum is a pointer.
In the second place: passPointer(*iNum);, the * is sitting in an expression. This means that it is the dereference operator, which means: "get the value pointed to by iNum". In this case the value pointed to by iNum is an int. As you will see later, passPointer is declared to take an argument of type pointer to int, so you cannot pass a plain int as an argument to passPointer. You should instead just pass iNum (as iNum is a pointer to int).
In the third place: void passPointer(int *pointer), the * is again sitting in a declaration. This means that it has the same meaning as in the first place - it says that pointer is a pointer (to int).
In the fourth place: cout << *pointer;, the * is again sitting in an expression. This means that, as in the second case, it is saying "dereference pointer and get the value that pointer is storing the address of".
This creates variable of name iNum and type int *:
int *iNum = new int(25);
This accept parameter of type int *:
void passPointer(int *pointer)
This passes the parameter of name iNum and type int *:
passPointer(iNum);
No need to think of pointers, these are all data types. Think of pointers only when you do pointer arithmetics and referencing, referencing. ;)
int**** is just a type.
Is it because I am dereferencing it at the parameter if I use *?
Yes. iNum has type pointer to int, *iNum has type int. If you had a function that takes an int, then you could pass it *iNum.
The passPointer() function takes a pointer-to-int. iNum is already a pointer-to-int, so you just pass it as-is. There is no need to deference it.

Cryptic C++ "thing" (function pointer)

What is this syntax for in C++? Can someone point me to the technical term so I can see if I find anything in my text?
At first I thought it was a prototype but then the = and (*fn) threw me off...
Here is my example:
void (*fn) (int&,int&) = x;
It can be rewritten to
typedef void (*T) (int&, int&);
T fn = x;
The 2nd statement is obvious, which should have solved that = x; question. In the 1st statement, we make T as a synonym as the type void(*)(int&, int&), which means:
a pointer to a function ((*…))
returning void
and taking 2 arguments: int&, int&.
That is a function pointer to a function taking two int reference parameters, which returns nothing. The function pointer is called fn and is being assigned the value in x.
This declares and initializes a function pointer.
The name of the variable is fn, and it points to a function with the following signature:
void pointedToFunction(int&, int&)
The variable fn is initialized to the value contained in x.
The pointed-to function can be called using the following syntax:
int a;
int b;
(*fn)(a,b);
This is equivalent to
int a;
int b;
pointedToFunction(a,b);
Function pointer.
http://www.newty.de/fpt/intro.html#what
^ Okay source for a beginner. :-)
This is a pointer to a function that takes two references to ints and returns void.
That seems like a function pointer to a method that takes two integer references and does not return anything. The pointer will be named fn. You are assigning it to the address of x, which is hopefully a function that matches this description.
It's a function pointer to a function that takes 2 integers as arguments and returns void. x must be a function name.
It's a function pointer variable that gets initialized to the stuff to the right of =.
The function type could be written like this:
typedef void func_t(int&,int&);
The function pointer than would be:
typedef func_t *fn_t;
With these definitions the variable declaration would be much clearer:
fn_t fn = ...;
Wikipedia page with a few links on the subject: http://en.wikipedia.org/wiki/Function_pointer

very basic c question

as we use pointers in the argument list of functions like
void f(int *);
this means that this function will receive a pointer to an integer
but what does this means
void f(int ***);
and
void f(int **=0)
void f(int ***);
means that the function receives a pointer to a pointer to a pointer to an int. This would work with it:
int x=42;
int *px=&x;
int **ppx=&px;
int ***pppx=&ppx;
f(pppx);
Now about the 2nd one, its a function that receives a pointer to a pointer to an int, and if you give it nothing, it defaults to 0.
int x=42;
int *px=&x;
int **ppx=&px;
f(ppx); // pt to pt to x
f(); // same as f(0)
UPDATE:
A practical application of this kind of double pointers is a memory allocation routine like:
bool alloc(T **mem, int count);
This function returns true/false depending on whether or not it worked and would update the pointer you pass in with the real memory address, like this:
T *mem;
verify(alloc(&mem, 100));
You pass in an uninitialized pointer and the function can overwrite it with a real value because you passed a pointer to the actual pointer. At the end, mem contains a pointer to valid memory.
Another application, more common but a lot less enlightening, is an array of arrays (so-called jagged arrays).
int ***
is a pointer to a pointer to a pointer to an int. Think of it as (((int*)*)*).
void f(int **=0)
This function takes a pointer to an int pointer as an argument, but can also be called without arguments in which case the argument will be 0.
void f(int ***);
Here f takes a pointer to pointer to pointer to an int.
void f(int **=0)
This function takes a pointer to pointer to an int as an argument, but this arguments is optional and has a default value of 0 (i.e null)
void f(int ***);
here the function argument is a pointer to a pointer to a pointer to an int (or more likely to many of them).
void f(int **=0)
and here it's just a pointer to a pointer to an int that gets initialized to be 0 (the pointer to the ... is 0, not the int) if the argument is not specified when the function is invoked (optional parameter).
What you are asking about is Multiple Indirection. That page sums up the problem very well, I highly recommend reading that entire page on pointers, it is golden.
void f(int ***);
As the other answers explain, this is a pointer to a pointer to a pointer to an int. It suggest to me that the programmer was not a very good programmer - he (and it was almost certainly a he) was too busy showing off how clever he was with 3 levels of indirection to consider the difficulty of maintaining overly obscure code like this. I've never had to use 3 levels of indirection in approx 20 years of programming in C and C++, and rarely use 2.