how to Understand complicated array declaration pointers, and & - c++

Here are two lines of code:
int (*parry)[10] = &arr // Line # 1
int *(&arrRef)[10] = ptrs // Line # 2
Line # 1:
parry is a pointer that points to an int array of size 10.
So does it mean:
parray[1] points to the address of arr,
parray[2] points to address of arr
...
parray[10] points to address or arr?
When would I use Line # 1?
Solution:
#include <iostream>
int main(
{
int arr[10] = { 3, 54 };
int (*parry)[10] = &arr;
std::cout << (*parry)[0] << " " << (*parry)[1] << " " << (*parry)[3] << " " << parry[4] << std::endl;
return 0;
}
Output:
3, 54, 0, hex address of arr at index 4.
It seems like what inside parry[0] is a pointer that points to arr associated with the index. So, parry[0] ---> arr[0].
Line # 2:
arrRef is a reference to an int array of size ten pointers. arrRef is referred to by ptrs.
So does it mean:
arry[1] is an int pointer? ...
arry[10] is an int pointer?
What example can this been used in?

When in doubt, see the Clockwise/Spiral Rule.
int (*parry)[10] = &arr;
parry is a pointer to an array of 10 ints.
int *(&arrRef)[10] = ptrs;
arrRef is a reference to an array of 10 pointers to int.
Example:
int main()
{
int arr[10];
int* ptrs[10];
int (*parry)[10] = &arr;
int *(&arrRef)[10] = ptrs;
}

Now I've cleaned up your question, I can see it wasn't what I originally thought. You say:
parray is a pointer that points to an int array of size 10
so clearly you figured out the clockwise/spiral/cdecl stuff already.
So does it mean: ... parray[10] points to address of arr
Firstly, arrays in C++ are indexed starting from zero, so you can access arr[0] .. arr[9] if there are 10 elements; arr[10] would be the eleventh, so is out of bounds.
Now, let's take your sentence apart:
parray is a pointer
right, it isn't an array, it's a pointer. Now, let's consider what it is a pointer to:
an int array of size 10
ok, if it points to that, then *parray must be (a reference to) the original array.
So, (*parray)[0] is the first element of the array, etc.
Note that you can easily test your intuition about all this by just printing things out, and seeing what you get. You'll either see pointers, and be able to compare the addresses, or you'll see integer values, or you'll get (hopefully informative) compile errors. Try it out!
Oh, and:
When would I use line 1?
Only if you need to re-seat it, in general. For example, if you want to choose one of two different arrays based on some logic, and then ... perform further logic on whichever was selected.
Next, you said
arrRef is a reference to an int array of size ten pointers.
Correct!
arrRef is refer to by ptrs
No, arrRef refers to an array, the array has size 10, and its 10 elements are pointers-to-int. Note this is not the same type as the first array!
Since references can be used with the same syntax as the thing they refer to, we can use arrRef as an array.
So, arrRef[0] is the first element of the array, and it is a pointer-to-int.
What example can this been used in?
The only common reason for using reference-to-array is to avoid pointer decay, allowing templates to deduce the number of elements.

I think that in this statement
//line1// int (*parry)[10] = $arr
^^^ ^^
there is a typo
There must be
//line1// int (*parry)[10] = &arr;
^^^ ^^
It is assumed that arr is an array of type int[10]. For example
int arr[10];
And this declaration
int (*parry)[10] = &arr;
declares a pointer to this entire array.
As for this declaration
//line2// int *(&arrRef)[10] = ptrs;
^^^
then it is assumed that ptrs is an array of type int *[10] That is elements of the array have type int *. They are pointers.
And this declaration
int * (&arrRef)[10] = ptrs;
declares a reference to this array. A reference is in fact is an alias of an array.
In C++ 2014 you could define a reference to an array simpler.
For example
decltype( auto )arrRef = ( ptrs );
Here is a demonstrative program
#include <iostream>
int main()
{
int a[10];
decltype( auto )ra = ( a );
std::cout << sizeof( a ) << std::endl;
std::cout << sizeof( ra ) << std::endl;
ra[0] = 10;
std::cout << a[0] << std::endl;
std::cout << ra[0] << std::endl;
}
The program output is
40
40
10
10

For parsing C declarations it is valuable to remember, in the words of Kernighan and Ritchie, that "the syntax is an attempt to make the declaration and the use agree" (K&R, TCPL, 5.12). In other words, you can treat a declaration as an expression and simply apply the operators in the proper order. That will show you what type the declared identifier must have.
For example, in int (*parry)[10] you first apply the * operator, because it is in parentheses. This indicates that parray is a pointer. Then you apply the [] operator, indicating that the result of the dereferencing was an array; the 10 indicates the number of elements. The obtained element is of type int. Summing up: parray was a pointer to an array of int.
Declarations of references in C++ can not be solved that way because there is actually no operator which would create a reference, or dereference one; both operations are implicit in C++. The & symbol is used to signify references in declarations only (perhaps somewhat confusingly, because in expressions it's used to take an address). But if you think of the & in declarations as a * substitute to signify a reference instead of a pointer you should still be able to parse any declaration.

Related

What is the difference between int* p and int** p in c++? [duplicate]

What is the difference between int* i and int** i?
Pointer to an integer value
int* i
Pointer to a pointer to an integer value
int** i
(Ie, in the second case you will require two dereferrences to access the integer's value)
int* i : i is a pointer to a object of type int
int** i : i is a pointer to a pointer to a object of type int
int*** i : i is a pointer to a pointer to a pointer to object of type int
int**** i : i is a pointer to a pointer to a pointer to a pointer to object of type int
...
int* pi
pi is a pointer to an integer
int **ppi
ppi is a pointer to a pointer to an integer.
EDIT :
You need to read a good book on pointers. I recommend Pointers on C by Kenneth Reek.
Let's say you're a teacher and have to give notes to one of your students.
int note;
Well ... I meant the whole class
int *class_note; /* class_note[0]: note for Adam; class_note[1]: note for Brian; ... */
Well ... don't forget you have several classes
int **classes_notes; /* classes_notes[0][2]: note for Charles in class 0; ... */
And, you also teach at several institutions
int ***intitute_note; /* institute_note[1][1][1]: note for David in class 1 of institute 1 */
etc, etc ...
I don't think this is specific to opencv.
int *i is declaring a pointer to an int. So i stores a memory address, and C is expecting the contents of that memory address to contain an int.
int **i is declaring a pointer to... a pointer. To an int. So i contains an address, and at that memory address, C is expecting to see another pointer. That second memory address, then, is expected to hold an int.
Do note that, while you are declaring a pointer to an int, the actual int is not allocated. So it is valid to say int *i = 23, which is saying "I have a variable and I want it to point to memory address 23 which will contain an int." But if you tried to actually read or write to memory address 23, you would probably segfault, since your program doesn't "own" that chunk of RAM. *i = 100 would segfault. (The solution is to use malloc(). Or you can make it point to an existing variable, as in int j = 5; int *i = &j)
Imagine you have a few friends, one of them has to give you something (a treasure... :-)
Say john has the treasure
int treasure = 10000; // in USD, EUR or even better, in SO rep points
If you ask directly john
int john = treasure;
int you = john;
If you cannot join john, but gill knows how to contact him,
int john = treasure;
int *gill = &john;
int you = *gill;
If you cannot even join gill, but have to contact first jake who can contact gill
int john = treasure;
int *gill = &john;
int **jake = &gill;
int you = **jake;
Etc... Pointers are only indirections.
That was my last story for today before going to bed :-)
I deeply believe that a picture is worth a thousand words. Take the following example
// Finds the first integer "I" in the sequence of N integers pointed to by "A" .
// If an integer is found, the pointer pointed to by P is set to point to
// that integer.
void f(int N, int *A, int I, int **P) {
for(int i = 0; i < N; i++)
if(A[i] == I) {
// Set the pointer pointed to by P to point to the ith integer.
*P = &A[i];
return;
}
}
So in the above, A points to the first integer in the sequence of N integers. And P points to a pointer that the caller will have the pointer to the found integer stored in.
int Is[] = { 1, 2, 3 };
int *P;
f(3, &Is[0], 2, &P);
assert(*P == 2);
&P is used to pass the address of P to the function. This address has type int **, because it's the address of a pointer to int.
int* i is the address of a memory location of an integer
int** is the address of a memory location of an address of a memory location of an integer
int* i; // i is a pointer to integer. It can hold the address of a integer variable.
int** i; // i is a pointer to pointer to integer. It can hold address of a integer pointer variable.
Neither is a declaration. Declaration syntax does not allow () around the entire declaration. What are these () doing there? If this is supposed to be a part of function declaration, include the whole function declaration thing in your question, since in general case the actual meaning of a declaration might depend on that. (Not in this one though.)
As for the difference... There is one * in the first and there are two *s in the second. Does it help? Probably not. The first one declares ias a pointer to int. The second one declares i as a pointer to int *. Does this help? Probably not much either. Without a more specific question, it is hard to provide a more meaningful answer.
Provide more context, please. Or, if this is actually as specific as it can get, read your favorite C or C++ book about pointers. Such broad generic questions is not something you ask on the net.
Note that
int *i
is not fully interchangeable with
int i[]
This can be seen in that the following will compile:
int *i = new int[5];
while this will not:
int i[] = new int[5];
For the second, you have to give it a constructor list:
int i[] = {5,2,1,6,3};
You also get some checking with the [] form:
int *i = new int[5];
int *j = &(i[1]);
delete j;
compiles warning free, while:
int i[] = {0,1,2,3,4};
int j[] = {i[1]};
delete j;
will give the warnings:
warning C4156: deletion of an array expression without using the array form of 'delete'; array form substituted
warning C4154: deletion of an array expression; conversion to pointer supplied
Both of these last two examples will crash the application, but the second version (using the [] declaration type) will give a warning that you're shooting yourself in the foot.
(Win32 console C++ project, Visual studio 2010)
Textual substitution is useful here, but beware of using it blindly as it can mislead you (as in the advanced example below).
T var; // var has type T
T* var; // var has type "pointer to T"
This works no matter what T is:
int* var; // pointer to int
char* var; // pointer to char
double* var; // pointer to double
// advanced (and not pure textual substitution):
typedef int int3[3]; // confusing: int3 has type "array (of size 3) of ints"
// also known as "int[3]"
int3* var; // pointer to "array (of size 3) of ints"
// aka "pointer to int[3]"
int (*var)[3]; // same as above, note how the array type from the typedef
// gets "unwrapped" around the declaration, using parens
// because [] has higher precedence than *
// ("int* var[3];" is an array (size 3) of pointers to int)
This works when T is itself a pointer type:
typedef int* T; // T is a synonym for "pointer to int"
T* var; // pointer to T
// which means pointer to pointer to int
// same as:
int** var;

Array and pointer

I am wondering how come the # number1 code not working
as I am trying to use increment operator to display the next following element in the array.
But the # number2 code works , and it was the same code but in a function
//# number 1 code
using namespace std;
int main(){
int arrays[5]={2,4,6,8,10};
for(int x=0;x<5;x++){
cout<<*arrays<<endl;
arrays++; //error: lvalue required as increment operand
}
}
//# number 2 code
using namespace std;
void display(int *arr,int size){
for(int x=0; x<5;x++){
cout<<*arr<<endl;
arr++; //This time no error!!!
}
}
int main(){
int arrays[5]={2,4,6,8,10};
display(arrays,5);
return 0;
}
That's because you cannot change the address of an array.
In # number 1 code when you do array++, you are actually trying to operate directly on the variable which is storing the base address of the array.
What you can try instead is something like below:
int *p = array;
p++;
Whereas in the case when you are calling a function passing the array's base address # number 2, you are implicitly doing what has been shown in the above code snippet.
This is a common problem for beginners. Arrays are not pointers!. Arrays are implicitly converted to pointers. That is where the confusion lies. Consider this:
int array[] = {1, 2, 3};
std::cout << *array << '\n';
What do you think is happening when we do *array. Does it really make sense to dereference an array? The array is being implicitly converted to a int * and then dereferenced. What about this:
int array[] = {1, 2, 3};
array++;
std::cout << *array << '\n';
This doesn't compile (as you found out for yourself). In this statement array++, the array is not implicitly converted to a pointer.
Arrays are converted to pointers when you pass them to functions that accept pointers. That makes it possible to do this:
int array[3] = {1, 2, 3};
display(array, 3);
An array is a sequence of objects stored on the stack. You access this sequence of objects as a pointer to the first object. Both arrays and pointers can be subscripted. They share many similarities but are fundamentally different.
To make your first example compile, subscript the array with x:
for (int x = 0; x < 5; x++) {
std::cout << arrays[x] << '\n';
}
Use :
int *arr = arrays;
arr++;
in code #1. It will work. This is because you need first to create a pointer to the base of the array which you can increment as in the second code, you have the pointer in the form of the passed argument to the function.

C++: Pointers in 2D-arrays are confusing

Can someone explain to me what is going on here? Consider the code
#include <iostream>
int main()
{
int A[2][2] = {{0}};
std::cout << A << std::endl; // First stdout line
std::cout << *A << std::endl; // Second stdout line
std::cout << *(*A) << std::endl; // Third stdout line
}
(Try the code here!)
It seems to me that A should be an array of 2 pointers to arrays, each of which should contain 2 pointers to ints. However, when running the code, the following is written to stdout:
0x7a665507cf80
0x7a665507cf80
0
To me, this makes it seem like the memory address of the first element in A (printed on the first stdout line) is the same as the memory address of the first element in *A. How is this possible, considering that A and *A are clearly two different arrays (since dereferencing A and *A gives different results)?
An alternative interpretation of the output is that the memory address 0x7a665507cf80 either contains the value 0x7a665507cf80 (i.e. a pointer located on that position—in this case A—points to itself) or 0, depending on if it is accessed from A or *A, which also doesn't really make sense to me.
int A[2][2] = {{0}}; This is a static 2D array, it's not a pointer to pointer, it's just a 1D array with special access.
The fact that it's not a point to pointer, but a 2D array on a 1D array means that A[0] or *A accesses the array and returns the 1D array that is the first row. Then the second dereferentiation gets the actual value. This generalizes to nD if you have int A[x][y][z][t]....
So the first two are the "same" address, but they are not the same type.

C++, static array, pointer, length

Can somebody explain to me why this code works?!!
I know A holds &A[0] and it is not a real pointer as if you cout<<&A you would get &A[0], but this result looks very strange to me.
int main()
{
double A[] = {2.4, 1.2, 4.6, 3.04, 5.7};
int len = *(&A+1) - A; // Why is this 5?
cout << "The array has " << len << " elements." << endl;
return 0;
}
And why this code doesn't work? And how can you make it work?
void test(double B[])
{
int len = *(&B+1) - B;
cout << len << endl;
}
int main()
{
double A[] = {2.4, 1.2, 4.6, 3.04, 5.7};
test(A);
system("pause");
return 0;
}
The expression is parsed like this:
(*((&A) + 1)) - A
The probably vexing part is that for some (but not all!) parts of this expression, the array decays to a pointer to the first element. So, let's unwrap this:
First thing is taking the address of the array, which gives you a pointer to an array of five elements.
Then, the pointer is incremented (+ 1), which gives the address immediately following the array.
Third, the pointer is dereferenced, which yields a reference to an array of five elements.
Last, the array is subtracted. It is only here that the two operands actually decay to a pointer to their first elements. The two are the length of the array apart, which gives the number of elements as distance.
&A takes the address of A itself. The type of A is double[5].
When you take the address of A itself and increment that pointer by 1, you are incrementing it by sizeof(double[5]) bytes. So now you have a pointer to the address following the A array.
When you dereference that pointer, you have a reference to the next double[5] array following A, which is effectively also a double* pointer to the address of A[5].
You are then subtracting the address of A[0] (an array decays into a pointer to its first element), and standard pointer arithmetic gives you 5 elements:
&A[5] - &A[0] = 5

Difference between the int * i and int** i

What is the difference between int* i and int** i?
Pointer to an integer value
int* i
Pointer to a pointer to an integer value
int** i
(Ie, in the second case you will require two dereferrences to access the integer's value)
int* i : i is a pointer to a object of type int
int** i : i is a pointer to a pointer to a object of type int
int*** i : i is a pointer to a pointer to a pointer to object of type int
int**** i : i is a pointer to a pointer to a pointer to a pointer to object of type int
...
int* pi
pi is a pointer to an integer
int **ppi
ppi is a pointer to a pointer to an integer.
EDIT :
You need to read a good book on pointers. I recommend Pointers on C by Kenneth Reek.
Let's say you're a teacher and have to give notes to one of your students.
int note;
Well ... I meant the whole class
int *class_note; /* class_note[0]: note for Adam; class_note[1]: note for Brian; ... */
Well ... don't forget you have several classes
int **classes_notes; /* classes_notes[0][2]: note for Charles in class 0; ... */
And, you also teach at several institutions
int ***intitute_note; /* institute_note[1][1][1]: note for David in class 1 of institute 1 */
etc, etc ...
I don't think this is specific to opencv.
int *i is declaring a pointer to an int. So i stores a memory address, and C is expecting the contents of that memory address to contain an int.
int **i is declaring a pointer to... a pointer. To an int. So i contains an address, and at that memory address, C is expecting to see another pointer. That second memory address, then, is expected to hold an int.
Do note that, while you are declaring a pointer to an int, the actual int is not allocated. So it is valid to say int *i = 23, which is saying "I have a variable and I want it to point to memory address 23 which will contain an int." But if you tried to actually read or write to memory address 23, you would probably segfault, since your program doesn't "own" that chunk of RAM. *i = 100 would segfault. (The solution is to use malloc(). Or you can make it point to an existing variable, as in int j = 5; int *i = &j)
Imagine you have a few friends, one of them has to give you something (a treasure... :-)
Say john has the treasure
int treasure = 10000; // in USD, EUR or even better, in SO rep points
If you ask directly john
int john = treasure;
int you = john;
If you cannot join john, but gill knows how to contact him,
int john = treasure;
int *gill = &john;
int you = *gill;
If you cannot even join gill, but have to contact first jake who can contact gill
int john = treasure;
int *gill = &john;
int **jake = &gill;
int you = **jake;
Etc... Pointers are only indirections.
That was my last story for today before going to bed :-)
I deeply believe that a picture is worth a thousand words. Take the following example
// Finds the first integer "I" in the sequence of N integers pointed to by "A" .
// If an integer is found, the pointer pointed to by P is set to point to
// that integer.
void f(int N, int *A, int I, int **P) {
for(int i = 0; i < N; i++)
if(A[i] == I) {
// Set the pointer pointed to by P to point to the ith integer.
*P = &A[i];
return;
}
}
So in the above, A points to the first integer in the sequence of N integers. And P points to a pointer that the caller will have the pointer to the found integer stored in.
int Is[] = { 1, 2, 3 };
int *P;
f(3, &Is[0], 2, &P);
assert(*P == 2);
&P is used to pass the address of P to the function. This address has type int **, because it's the address of a pointer to int.
int* i is the address of a memory location of an integer
int** is the address of a memory location of an address of a memory location of an integer
int* i; // i is a pointer to integer. It can hold the address of a integer variable.
int** i; // i is a pointer to pointer to integer. It can hold address of a integer pointer variable.
Neither is a declaration. Declaration syntax does not allow () around the entire declaration. What are these () doing there? If this is supposed to be a part of function declaration, include the whole function declaration thing in your question, since in general case the actual meaning of a declaration might depend on that. (Not in this one though.)
As for the difference... There is one * in the first and there are two *s in the second. Does it help? Probably not. The first one declares ias a pointer to int. The second one declares i as a pointer to int *. Does this help? Probably not much either. Without a more specific question, it is hard to provide a more meaningful answer.
Provide more context, please. Or, if this is actually as specific as it can get, read your favorite C or C++ book about pointers. Such broad generic questions is not something you ask on the net.
Note that
int *i
is not fully interchangeable with
int i[]
This can be seen in that the following will compile:
int *i = new int[5];
while this will not:
int i[] = new int[5];
For the second, you have to give it a constructor list:
int i[] = {5,2,1,6,3};
You also get some checking with the [] form:
int *i = new int[5];
int *j = &(i[1]);
delete j;
compiles warning free, while:
int i[] = {0,1,2,3,4};
int j[] = {i[1]};
delete j;
will give the warnings:
warning C4156: deletion of an array expression without using the array form of 'delete'; array form substituted
warning C4154: deletion of an array expression; conversion to pointer supplied
Both of these last two examples will crash the application, but the second version (using the [] declaration type) will give a warning that you're shooting yourself in the foot.
(Win32 console C++ project, Visual studio 2010)
Textual substitution is useful here, but beware of using it blindly as it can mislead you (as in the advanced example below).
T var; // var has type T
T* var; // var has type "pointer to T"
This works no matter what T is:
int* var; // pointer to int
char* var; // pointer to char
double* var; // pointer to double
// advanced (and not pure textual substitution):
typedef int int3[3]; // confusing: int3 has type "array (of size 3) of ints"
// also known as "int[3]"
int3* var; // pointer to "array (of size 3) of ints"
// aka "pointer to int[3]"
int (*var)[3]; // same as above, note how the array type from the typedef
// gets "unwrapped" around the declaration, using parens
// because [] has higher precedence than *
// ("int* var[3];" is an array (size 3) of pointers to int)
This works when T is itself a pointer type:
typedef int* T; // T is a synonym for "pointer to int"
T* var; // pointer to T
// which means pointer to pointer to int
// same as:
int** var;