very basic c question - c++

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.

Related

the purpose of function parameters with two indirection operators (C++)

What is the purpose of a function parameter that has two indirection operators?
Since a call by reference is changing the value of the original variable I thought that a function parameter with two indirection operators might change the address of the original value.
But as my attemp below shows, it does not:
void addrchanger(int**);
int main()
{
int value1 = 4;
int* value1ptr = &value1;
std::cout<<&value1<<std::endl;
addrchanger(&value1ptr);
std::cout<<&value1<<std::endl;
//the address of value1 doesn't change.
}
void addrchanger(int** foo)
{
//this is an attempt to change the address of value1 to the next slot
++**foo;
}
The purpose is to pass a pointer to pointer(s) or a pointer to array(s). Such practise is C-like for historical functions like main() char** argv (that is why you also want an argc, because the size cannot be deduced by the pointer). It is also used when you want to be returned a pointer, so you pass a pointer to a pointer, like in many Win32 functions.
For example in StringFromIID
HRESULT StringFromIID(
REFIID rclsid,
LPOLESTR *lplpsz
);
you would pass a double pointer as the 2nd parameter (a wchar_t**) in order to be returned a pointer, which them must be deallocated like the doc says.
Avoid that completely nowadays in C++ and use std::vector in whatever depth is necessary.
The void addrchanger(int** foo) function can change:
the value: (**foo)++ making int value1 to 5
and address: (*foo)++ making value1ptr point to the next space after value1
I believe you expected the ++**foo to move value1 to the next position, which is not the case.
The pointer to pointer is also useful for matrix declarations, but most libraries such as the GNU scientific library, BLAS, OpenGL glLoadMatrixf(), prefer the use of a single pointer.
When p is of type int **,
++**p
increases the value of the int represented by **p.
In order to change the address of the int pointed to, you would use
++*p
With direct access to your variable, you would use one * less for everything:
int *p;
++*p; // increment the int value
++p; // increment the pointer
But inside such a function, every arguments is just a copy, so if you want to change something outside, you need a pointer to it, which means that one more * is used for everything.
function f(int **p) {
++**p; // increment the int value
++*p; // increment the pointer
// you can also increment the argument
// but you can't know whether it will then
// still point to another int pointer:
++p
}
In addition, you can use & instead of * in C++ which is used only for declaring a variable as a reference and then works like a secret, hidden pointer. You use one less * again, like outside the function at the beginning.
function f(int *&p) {
++*p; // increment the int value
++p; // increment the pointer
// you can also not increment the reference itself,
// as it is a hidden pointer.
}
This sounds dangerous because who would want secret pointers? But it is very common in C++ because people like typing less * all over the place.

Can a pointer take arguments? What is the difference between these 3 kind of pointers

I want to know what is the meaning of the following statements.
int *abc(int,int);
int (*abc)(int,int);
and how these pointers are different from the ordinary pointer. ex:
int *ptr;
Thank you
Can a pointer take arguments?
No, a pointer is just a variable which stores address of a memory location.
int *abc(int,int);
This is a declaration of function abc which takes two arguments, both of type int, and returns a pointer to an int type.
int (*abc)(int,int);
Here, abc is a pointer that can point to a function which takes two int type arguments and returns an int.
Say, if you have a function fun:
int fun(int a, int b) {
return a + b;
}
abc can point to fun(), like this:
abc = fun;
then you can call function fun using abc pointer, like this:
abc(4, 5);
how these pointers are different from the ordinary pointer. ex:
int *ptr;
Here, ptr is a pointer which can store the address of an int type.
Hence, all the pointers store some memory location, the difference lies in the address of a type they point to.
assuming C/C++
this: int *abc(int,int); is a prototype of function returning a pointer to int and taking two arguments of type int
this: int (*abc)(int,int); is a declaration of a pointer to function returning int and taking two arguments of type int

C++ rvalue and pointer of pointer when should I use it?

Please consider these 2 lines of code
void doStuff(int ** i)
void doStuff2( int && i)
in the first one I assume that it is a pointer of pointer and the second is an rvalue,
I came across this question and it explains the rvalue but when should I use the first and when should I use the second ?
could you clarify this to me please ?
int ** i is a pointer to a pointer.
Generally, use this sparingly, as this may have different meanings and you have better ways to express that in C++.
It may be a pointer to single variable containing a pointer to a single int:
int value = 0;
int * pValue = &value;
int ** ppValue = &pValue;
However, each may also be a pointer to the first element of an array:
int valuesA[1000], valuesB[100], valuesC[10];
int * pValues[] = { valuesA, valuesB, valuesC };
// these are actually pointers to the first element of the array
int ** ppValues = pValues;
Use this only with clear documentation how to access elements, how to know the element sizes, and who is responsible for freeing (if any), how long the pointers are valid etc.
Usually, if you have such an array / matrix, you certainly should wrap it behind a safe-to-use interface, or replace it alltogether e.g. with a vector<vector<int>>.
Even for the single-int use cases there are usually better options. E.g. a function signature that allows to modify a pointer, a reference to a pointer would be more suitable:
bool SelectValue(int *& p) { ... }
int && is a rvalue reference.
Unlike the int **, this is not a double indirection.
It is, roughly a reference that can also bind to a temporary value.
("Normal" references cannot).
A Brief Introduction to Rvalue References

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++?

Confusion over C++ pointer and reference topic

What is the difference between the following parameter passing mechanisms in C++?
void foo(int &x)
void foo(int *x)
void foo(int **x)
void foo(int *&x)
I'd like to know in which case the parameter is being passed by value or passed by reference.
void foo(int &x)
passes a reference to an integer. This is an input/output parameter and can be used like a regular integer in the function. Value gets passed back to the caller.
void food(int *x)
passes a pointer to an integer. This is an input/output parameter but it's used like a pointer and has to be dereferenced (e.g. *x = 100;). You also need to check that it's not null.
void foo(int **x)
passes a pointer to a pointer to an integer. This is an input/output parameter of type integer pointer. Use this if you want to change the value of an integer point (e.g. *x = &m_myInt;).
void foo(int *&x)
passes a reference to a pointer to an integer. Like above but no need to dereference the pointer variable (e.g. x = &m_myInt;).
Hope that makes sense. I would recommend using typedefs to simplify the use of pointers and reference symbols.
Just adding: I think your spacing is misleading. Maybe things get a bit clearer if you change it.
The , &, * and so on is part of the type, so keep it with the type:
void foo(int& x)
void foo(int* x)
void foo(int** x)
void foo(int*& x)
int& is an reference to an int, int* is a pointer to an int, int** is a pointer to an pointer to an int, and so on.
You still need to read the types from right to left - int*& being a reference to an pointer to an int. But that's consistent.
I think this is easier to read and represents better what is meant.