what is pointer past the end of an object means? - c++

In C++ Primer, Chapter 2, "Variables and Basic Types", it says:
it is possible for a pointer to an object and a pointer one past the end of a different object to hold the same address.
I'm not a native speaker, and I think that's why I'm a bit confused by the sentence "a pointer one past the end of an object". Would anyone one tell me what it means please?

It means that after
int a[] = { 1, 2 };
float b;
it's possible that (void *) &a[2] == (void *) &b may compare as true.
&a[2] (or equivalently, a+2) is a pointer just past the end of a, because the array only contains elements with indices 0 and 1.
Normally, out-of-range array indices are completely invalid (accessing a[2] is not allowed, nor is even computing &a[3]), but there is a special exception for computing the address just past the end of an array, because as it turned out, that is quite useful, for example when iterating over an array and you need an end value to know when to stop the loop.

Suppose you have an array, int foo[5] = {1,2,3,4,5};. It's laid out in memory like this:
-----------
|1|2|3|4|5|
-----------
It's legal to have a pointer that points to any member of the array; but it's also legal for a pointer to point one past the end of the array (usually to signal that it has reached the end of the array when doing an STL algorithm using iterators) - although it isn't legal to dereference that pointer. Like so:
-------------
|1|2|3|4|5|?|
-------------
^ ^
| |
p q
p is a pointer into the array; q is a pointer one-past-the-end.
Now, suppose you also have an array const char bar[3] = "Hi";. It's possible that the two arrays have been allocated next to each other in memory, like so:
<--foo---> <-bar->
-----------------
|1|2|3|4|5|H|i|0|
-----------------
^ ^
| |
p q
Then q is both a one-past-the-end for foo, and also pointing to the physical location for bar[0].

"one past" means "+1 operation on the pointer". The following code generates:
0x7ffffcf6a848
0x7ffffcf6a84c
0x7ffffcf6a84c
As you can see, the address of "one past a", i.e., &a + 1 is the same as &b.
int a = 2;
int b = 3;
cout<< &a << endl << &a + 1 << endl << &b <<endl;

Related

Address of the Pointer pointing to the first element

In http://www.fredosaurus.com/notes-cpp/arrayptr/array-diagrams.html website, it states that
Pointers hold the memory address of other data and are represented by a black disk with an arrow pointing to the data it references.
For example,
int a[5]; // Allocates memory for 5 ints.
. . .
a[0] = 1;
for (int i=1; i<5; i++) {
a[i] = a[i-1] * 2;
}
would result in.
My question is how can I print the address of the pointer pointing to the array?
I know that &a or &a[0] gives us the address of the first element. But how can I access the pointer pointing the array?
An array and a pointer are not the same thing. What the memory really looks like is this:
a
-------
| 1 | a[0]
-------
| 2 | a[1]
-------
| 4 | a[2]
-------
| 8 | a[3]
-------
| 16 | a[4]
-------
So if you were to print a and &a, you would see that they print the same value.
If the array is on the stack as it would be in your example code then the image below is a more accurate representation of how the memory would be laid out. I've also added an additional pointer to hopefully add some clarification.
int a[5];
a[0] = 1;
for (int i=1; i<5; i++)
a[i] = a[i-1] * 2;
int* b = a;
It may be easier to think of the [] notation of defining an array as a little syntactic sugar. When calling functions and passing in a the function will be called with the address of a[0] being passed in.
When passing b to a function it's the value that will be passed in, which is the address of a.
You can have lots of pointers pointing to a[0].
Just as for a pointer to the array, create a pointer variable pointing to a[0] and then take a pointer to it. You will have one pointer to one pointer pointing to the array.
I know that &a or &a[0] gives us the address of the first element.
Technically. &a is in fact the address of the array itself. It just has the same value as address of the first element. But note that the type of the expression is different. &a is a int (*)[5] (pointer to an array of 5 integers), while &a[0] is a int* (pointer to an integer).
My question is how can I print the address of the pointer pointing to the array?
First step is to have a pointer. You don't have any pointer variables in your example. An array is not a pointer. The sentence "The actual array variable, a in this example, is a pointer to the memory for all of its elements." of the page is very misleading, as an array is not a pointer object. The drawn diagram is not correct for the program.
Here is a program that is correct according to the diagram:
int array[5]; // Allocates memory for 5 ints.
int* a = array; // a pointer to the first element of the array
a[0] = 1;
for (int i=1; i<5; i++) {
a[i] = a[i-1] * 2;
}
Here we actually have a pointer. Now you can print the address of the pointer:
std::cout << &a;

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

how to Understand complicated array declaration pointers, and &

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.

Pointer of array, where does the information of memory space of each element of that array store?

For example:
int *p;
int a[2] = {1, 2};
p1 = a;
I was wondering where does c++ store the information of memory space of each element? I mean, when I do this:
cout << p << endl;
I only can get the memory address of that array, there is obviously no information related to the "memory length" of single element. But I think there should be some place that the language can refer to the space of memory space of each element. Since if I go on the call this:
cout << *++p << endl;
I can get the second element of that array no matter what type of element in that array and the corresponding space of memory of single element. The language is able to automatically kind of jump over the certain space memory to get the right start place of the next element and its address.
So, again, my question is: Where is the information of the memory space of element in that array stored? Or is there something like "\0" at the end of each element to signify the end of one element in that array, so the *++p is about to get to the next right place?
where does the information of memory space of each element of that array store?
When you use:
int *p;
int a[2] = {1, 2};
p = a;
memory for the elements of a are in the stack. They memory is contiguous. p points to the first element of a.
Regarding:
I can get the second element of that array no matter what type of element in that array and the corresponding space of memory of single element. The language is able to automatically kind of jump over the certain space memory to get the right start place of the next element and its address.
Yes, that is correct.
From a purely numerical point of view,
p+1 == p + sizeof(*p)
sizeof(*p) can be computed at compile time. There is no need for any run time information. There is no need for markers to signify the end of an element.
The memory in an array is contiguous, so yes incrementing a pointer will get you from one element to the next element.
The way that it knows how far in memory to go to get to the next element is by the type of the pointer, in this case it is an int*, so it knows to increment by sizeof(int) to get to the next element.
It doesn't. C++ has no runtime information about the types of variables. It simply interprets the data behind the pointer as the type you gave to it in your source code. Take the following code for example:
void f(int *) { std::cout << "Integerpointer" << std::endl; }
void f(char *) { std::cout << "Charpointer" << std::endl; }
int i = 9;
int * p = &i;
f(p);
This will print Integerpointer because the compiler knows at compile time that the type of p is int *. The following code will print Charpointer because the type is changed (the compiler interprets the pointer different):
void f(int *) { std::cout << "Integerpointer" << std::endl; }
void f(char *) { std::cout << "Charpointer" << std::endl; }
int i = 9;
int * p = &i;
f(reinterpret_cast<char *>(p));
The compiler substitutes f() with the matching function call in your source code. So the interpretation of the underlying data is done at compiletime.
To address your array question:
The compiler knows the sizes of the elements at compile time. It then adjusts the pointer addition when accessing the elements and puts the size hard coded in your machine code. If you know a bit assambly you can look at the assambly code and see this effect.

Why is it a compile error to assign the address of an array to a pointer "my_pointer = &my_array"?

int my_array[5] = {0};
int *my_pointer = 0;
my_pointer = &my_array; // compiler error
my_pointer = my_array; // ok
If my_array is address of array then what does &my_array gives me?
I get the following compiler error:
error: cannot convert 'int (*)[5]' to 'int*' in assignment
my_array is the name of an array of 5 integers. The compiler will happily convert it to a pointer to a single integer.
&my_array is a pointer to an array of 5 integers. The compiler will not treat an array of integers as a single integer, thus it refuses to make the conversion.
&my_array is the address at which the value of my_array is stored, i.e., it is the address of the address of the array and has type int**.
This would be a fascinating topic for research on neuroscience, semantics, and software development. Even though we can explain the difference between my_array and &my_array, and even though we can repeat the mantra that "arrays are (or are not) pointers", this distinction is still confusing.
Usually when we take the address of something with the "&" operation, we arrive at a completely different value.
int x;
x=5;
cout <<x << " "<<&x<<endl;
First of all, let's challenge this intuition. A pointer can be accidentally equal to the value it is pointing at:
int* x;
x=(int*)(&x);
cout <<"same: "<<x << " "<<&x<<endl;
So in some contexts semantically different things can evaluate to the same thing. But just because two expressions are equal in the current context does not mean that they are interchangeable.
int w=3;
int* ip=&w;
void* vp=&w;
cout <<"Equal: "<<ip<<" "<<vp<<" "<<(ip==vp)<<endl;
cout <<"But not interchangeable: "<<ip+1<<" "<<vp+1<<" "<<(ip+1==vp+1)<<endl;
The same happens with pointers to arrays. A pointer to an array is often technically "equal" to an array itself, but since they have different semantics, there are situations in which they are not interchangeable. Try this one:
int my_array[5] = {5,6,7,8,9};
cout <<my_array[0]<<endl; // output 5
cout <<(&my_array)[0]<<endl; // outputs the address of the first element
cout <<sizeof my_array[0]<<endl; // outputs 4
cout <<sizeof (&my_array)[0]<<endl; // outputs 20