int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int (*parr)[10] = &arr;
//prints address of arr and the value 1
cout << parr << " " << *parr[0];
//what is this doing?
parr++;
//prints (what looks like the address of arr[1]) and some long number -8589329222
cout << parr << " " << *parr[0];
I thought parr++ would increment the address that parr is pointing to so that *parr[0] is now the address of *parr[1]. Where am I wrong?
You're assuming parr++ increments by one word. It doesn't. It increments by the size of *parr, which in thise case is an int[10], so it's incrementing by the size of 10 integers (probably 40 bytes).
You only need a pointer to the start of the array.
int* parr = arr; // points to the 0 element
parr++; // poInts to the first element, 1.
Related
I have come across a piece of example code that uses pointers and a simple subtraction to calculate the number of items in an array using C++.
I have run the code and it works but when I do the math on paper I get a different answer.
There explanation does not really show why this works and I was hoping someone could explain this too me.
#include <iostream>
using namespace std;
int main() {
int array[10] = {0, 9, 1, 8, 2, 7, 3, 6, 4, 5};
int stretch = *(&array + 1) - array;
cout << "Array is consists of: " << stretch << " numbers" << endl;
cout << "Hence, Length of Array is: " << stretch;
return 0;
}
From: https://www.educba.com/c-plus-plus-length-of-array/
When I run the code I get the number 10.
When I print the results of *(&array + 1) and array by
cout << *(&array+1) << endl; cout << array << endl;
I get of course two hex address's.
When I subtract these hex numbers I get 1C or 28???
Is it possible that C++ does not actually give the hex results or their translation to decimal but rather sees these numbers as addresses and therefore only returns the number of address slots remaining?
That is the closest I can come to an explanation if some one with more knowledge than I could explain this I would be very grateful.
Let's take one step back and take it step-by-step to see if it will help. Continuing from my comment, the problem you are having difficulty with is one of type.
Let's take the array iteself:
int array[10] = {0, 9, 1, 8, 2, 7, 3, 6, 4, 5};
On access, an array is converted to a pointer to the first element in the array (e.g. the address of the first element) subject to caveats not relevant here. So when you say array, you have type int *, a pointer to the first element in array.
Now what happens when I take the address of the array? (&array in)
int stretch = *(&array + 1) - array;
When you take the address of the array, the result is the same address as array, but has type int (*)[10] (a pointer-to-array-of int[10]). When you add 1 to that pointer (recall type controls pointer arithmetic), you get the address for the pointer to the next array of int[10] in memory after array -- which will be 10 int after the first element of array.
So *(&array + 1) gives you the address to the next array of int[10] after array, and then dereference is only needed for type compatibility. When you dereference an int (*)[10] you are left with int[10] -- which on access gives you the address of the first element of that array (one after the original)
Think through the types and let me know if you have further questions.
You forgot a small detail of how pointer addition or subtraction works. Let's start with a simple example.
int *p;
This is pointing to some integer. If, with your C++ compiler, ints are four bytes long:
++p;
This does not increment the actual pointer value by 1, but by 4. The pointer is now pointing to the next int. If you look at the actual pointer value, in hexadecimal, it will increase by 4, not 1.
Pointer subtraction works the same way:
int *a;
int *b;
// ...
size_t c=b-a;
If the difference in the hexadecimal values of a and b is 12, the result of this subtraction will not be 12, but 3.
When I subtract these hex numbers I get 1C or 28 ???
There must've been a mistake with your subtraction. Your result should be 0x28, or 40 (most likely you asked your debugger or compiler to do the subtraction, you got the result in hexadecimal and assumed that it was decimal instead). That would be the ten ints you were looking for.
I will try it with 5 items
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int array[] {1,2,3,4,5};
int items= sizeof(array)/sizeof(array[0]);
cout << items << endl;
int items2 = *(&array +1) - array;
cout << items2 << endl;
cout << array << endl;
cout << *(&array +1) << endl;
return 0;
}
root#localhost:~/Source/c++# g++ arraySize.cpp
root#localhost:~/Source/c++# ./a.out
5
5
0x7fe2ec2800
0x7fe2ec2814
using https://www.gigacalculator.com/calculators/hexadecimal-calculator.php to subtract the numbers from each other
I get
14 hex
20 decimal.
that fits with the 4 bytes to an integer.
thanx guys :)
this is an edit done on the 12th of december melbourne time ::
I have still had questions on this topic and something did not fit right with me about the entire route to counting array items via this code.
I found something I think is interesting and again would love to know why ( I shall try to explain it as best I can my self anyway)
*(&array + 1) is the question.
lets have a look at it.
as arrays are at there very nature in c and c++ only pointers to the first element in the array how can this work.
I shall use a small set of cout calls to see if I can find out whats happening.
#include <iostream>
using namespace std;
int main(int argc, char* argv[]){
int array[] {1,2,3,4,5,6,7,8,9,10};
int size {0};
size = *(&array + 1) - array;
cout << "size = *(&array + 1) - array = " << size << endl;
cout << "*(&array + 1) = " << *(&array + 1) << endl;
cout << "(&array + 1) = " << (&array + 1) << endl;
cout << "(array + 1) = " << (array + 1) << endl;
cout << "&array = " << &array << endl;
cout << "array = " << array << endl;
cout << "*(&array) = " << *(&array) << endl;
cout << "*(array) = " << *(array) << endl;
cout << "*array = " << *array << endl;
return 0;
}
again this is off proot in my phone so still under root with no systemd.
root#localhost:~/Source/c++# g++ arrayPointerSize.cpp
root#localhost:~/Source/c++# ./a.out
size = *(&array + 1) - array = 10
*(&array + 1) = 0x7ff6a51798
(&array + 1) = 0x7ff6a51798
(array + 1) = 0x7ff6a51774
&array = 0x7ff6a51770
array = 0x7ff6a51770
*(&array) = 0x7ff6a51770
*(array) = 1
*array = 1
we see that as a pointer array can be called with * too derefernce the pointer and give the variable held in position [0] in the array.
when calling &array or reference too array we get the return of the address at the first position in the array or [0].
when calling just array we also get the address for the first position in the array or [0].
when calling *array the * is working as it does for pointers and it is dereferencing the arrays first position [0] to give the variable.
now things get a little interesting.
*(array) also dereferences the array as is seen by its value being given as 1 in this instance.
yet *(&array) does not dereference the array and returns the address to the first position in the array.
in this instance memory address 0x7ff6a51770 is the first spot in the array array = 0x7ff6a51770
and &array (reference to the pointer of the position in memory that is the first spot in the array) gives the same address 0x7ff6a51770.
it is also of note in this instance to remind us of the fact that *(&array) is also returning the first possition in the array and *(array) is not
so we can not dereference a pointer too a position in memory as its variable is the position in memory.
if array and &array give the same answer as array is a pointer too the memory position in the first spot in our array and a reference to
this pointer.
why the different answer for (array + 1) and (&array + 1).
we get the memory address 0x7ff6a51774 for (array + 1) which is in line with an integer taking four bytes on my linux or
the addition of four bytes in memory past the first spot in the array (second array spot) but (&array + 1) gives a different answer.
if we follow the bytes and the code we see that (&array + 1) actually gives us the memory address four bytes after the end of the array.
so pointer too memory address add one gives the amount of bytes the variable type is past the memory address for the start of the array
and the reference to the pointer too the memory address add one gives the address the amount of bytes the variable type is after the last ?? spot in the array.
how then can array and &array return the same answer if (array + 1) and (&array + 1) do not.
it seems to me that the & reference when working with arrays overloads the + operator when doing arithmatic.
this would explain the difference in answers as straight &array has no operator too overload so returns the same answer as calling for
straight array
this small peice of code also shows that the use of pointers using *(&array + 1) is a very bad way to show a way to find array size with
pointers as really arrays are pointers and *(&array + 1) and (&array + 1) give the same result.
the heavy work was really being done by the reference operator &.
I may still be missing something here as I have used cout directly with the different experssions and being a stream it may
be limited in its ability to take advantage of what the reference operator is really doing when working with arrays.
I am still learning this language but I shall for sure keep this in mind as I dive deaper into c++.
I believe other than a few other trials with variables that the true answer will be found when reading the source for GCC g++.
I am not ready for that yet.
I have the following code:
#include <iostream>
using namespace std;
int main()
{
int g[] = {9,8};
int (*j)[2] = &g;
cout << "*(j):" << *(j) << endl;
cout << "j:" << j << endl;
cout << "&j:" << &j << endl;
cout << "&(*j)" << &(*j) << endl;
cout << "*(*j):" << *(*j) << endl;
return 0;
}
which ouputs:
*(j):0x7fff5ab37c7c
j:0x7fff5ab37c7c
&j:0x7fff5ab37c70
&(*j)0x7fff5ab37c7c
*(*j):9
I think that j is a pointer to an array of two integer.
And &g is the address of the whole array.
Then j store the address of the whole array.
And so I use the *(j), it will dereference the first element in the array.
But the result said that *(j) store the array address the same value as j.
I cannot figure out how this happened.
I think that j is a pointer to an array of two integer.
And &g is the address of the whole array.
That is correct.
And so I use the *(j), it will dereference the first element in the array.
This is not. *j gives you the array itself. When you insert it to cout, it decays to a pointer again (this time to a pointer to its first element, type int*) and its value is printed.
It's in effect the same as if you wrote cout << g.
"I think that j is a pointer to an array"
Yes, it is. And that's also the reason why *j output the same address as outputting g would do. In this case an array decays into the pointer and that's why even outputting j yields the same result.
The fact that the same address is outputted might make you think that j and *j are the same pointers, however they are not. Their type is different (a fact that actually matters):
int g[] = {9,8}; // int[]
int (*j)[2] = &g; // int (*)[2]
so using *j becomes equivalent to using g directly, just like *(*j) becomes equivalent to *g.
And &(*j) is nothing but j, which is initialized with an address of an array (an address taken from decayed g, i.e. an address of the first element of this array).
So why j and *j outputs the same address and *(*j) outputs the value of first element?
Because of the type of j being int (*)[2]. A simple example:
int g[] = {9,8};
int (*j)[2] = &g; // j points to the first element as well
cout << *((int*) j);
outputs 9.
I am trying to create a simple version of a vector. It seems to be working if I look only at what I am storing, but there is one thing that concerns me. Here is my code:
#include <iostream>
using namespace std;
int main(){
char* arr = new char[1];
int size = 1; // current size of the array
int num_chars = 0; // how many characters are stored so far
char c;
while (true)
{
cout << ">";
cin >> c;
if (c == '!') break;
if (num_chars == size)
{
size *= 2;
char* new_arr = new char[size];
cout << "Old array address: " << &arr << endl;
cout << "New array address: " << &new_arr << endl;
for (int i = 0; i < size/2; i++) // copy arr to new_arr
new_arr[i] = arr[i];
delete[] arr;
arr = new_arr;
}
arr[num_chars++] = c;
for (int i = 0; i < num_chars; i++)
cout << arr[i];
cout << endl;
cout << &arr << endl;
}
delete[] arr;
return 0;
}
the program accepts characters one at a time, and they are stored in an array which grows dynamically, finishing when you enter an exclamation mark. I added some cout statements to check my input and where the arrays are being stored.
When I allocate new_arr it gets a new address, then I copy over the memebers of arr to the new arr, delete arr, and assign arr to point to new_arr. The part that concerns me is that when I check the memory locations of arr after it gets reassigned, it's the same as it was before, so it looks like I'm just writing past the end of the original array. How can I correctly reassign the pointer to the new array?
Here is some sample output:
>a
a
0x7fff5fbff760
>b
Old array address: 0x7fff5fbff760
New array address: 0x7fff5fbff748
ab
0x7fff5fbff760
>c
Old array address: 0x7fff5fbff760
New array address: 0x7fff5fbff748
abc
0x7fff5fbff760
You are printing out addresses of pointers themselves, not addresses of the arrays (i.e. the contents of the pointers).
The location in memory where you store the address of the array (i.e. the address of variable arr) stays the same. It's not supposed to change. Thus, &arr is always the same. But the value stored in that location does change (as it would be expected).
Change the code to
cout << "Old array address: " << static_cast<void*>(arr) << endl;
and see the difference.
(static_cast<void*>(arr) casts type of arr from char* to void*. The reason to do this is that cout treats char* as a pointer to null-terminated string, and prints the contents of the string instead of the pointer's value. However, if we change the type of the pointer to something that cout does not interpret (e.g. void*), then cout will just print the address.)
int arr[][3] = {{1,3},{2,3},{6,7}};
cout << arr[0] << endl; // W/O col' somehow give you the address, not the element.
cout << arr[0][0] << endl;
I am curious as to why arr[0] prints the address, not the element.
It seems like somehow it's ignoring its dereference operator.
I'd be appreciated if you could help me in terms of a pointer or in depth.
Thank you.
Since arr is a two-dimensional array, arr[0] will give you an entire row (more precisely, the address of that row).
More precisely, since arr is of type int[][3] arr[0] is of type int[3], which decays to int *. Hence, cout << arr[0] << endl; prints a pointer.
array[0] holds the address of the array[0][0...n-1] values so only cout << arr[0]; prints the address since arr[0] is the pointer to the values in arr[0][0..n-1]
If you want specific value of an two dimensional array then you need to give both x and y index like
array[0][0] ... array[0][n-1]
I have the following code:
#include <iostream>
using namespace std;
int main()
{
int g[] = {9,8};
int (*j)[2] = &g;
cout << "*(j):" << *(j) << endl;
cout << "j:" << j << endl;
cout << "&j:" << &j << endl;
cout << "&(*j)" << &(*j) << endl;
cout << "*(*j):" << *(*j) << endl;
return 0;
}
which ouputs:
*(j):0x7fff5ab37c7c
j:0x7fff5ab37c7c
&j:0x7fff5ab37c70
&(*j)0x7fff5ab37c7c
*(*j):9
I think that j is a pointer to an array of two integer.
And &g is the address of the whole array.
Then j store the address of the whole array.
And so I use the *(j), it will dereference the first element in the array.
But the result said that *(j) store the array address the same value as j.
I cannot figure out how this happened.
I think that j is a pointer to an array of two integer.
And &g is the address of the whole array.
That is correct.
And so I use the *(j), it will dereference the first element in the array.
This is not. *j gives you the array itself. When you insert it to cout, it decays to a pointer again (this time to a pointer to its first element, type int*) and its value is printed.
It's in effect the same as if you wrote cout << g.
"I think that j is a pointer to an array"
Yes, it is. And that's also the reason why *j output the same address as outputting g would do. In this case an array decays into the pointer and that's why even outputting j yields the same result.
The fact that the same address is outputted might make you think that j and *j are the same pointers, however they are not. Their type is different (a fact that actually matters):
int g[] = {9,8}; // int[]
int (*j)[2] = &g; // int (*)[2]
so using *j becomes equivalent to using g directly, just like *(*j) becomes equivalent to *g.
And &(*j) is nothing but j, which is initialized with an address of an array (an address taken from decayed g, i.e. an address of the first element of this array).
So why j and *j outputs the same address and *(*j) outputs the value of first element?
Because of the type of j being int (*)[2]. A simple example:
int g[] = {9,8};
int (*j)[2] = &g; // j points to the first element as well
cout << *((int*) j);
outputs 9.