Value Of Pointers - c++

In my book, it says Pointers are addresses and have a numerical value. You can print out the value of a pointer as cout << (unsigned long)(p)
Write code to compare p,p+1,q, and q+1. Explain the results, Im not sure what the book wants me to so here's what I have. Does anyone Know if I am doing this right
int num = 20;
double dbl = 20.0;
int *p = &num;
double *q = &dbl;
cout << (unsigned long)(q) << endl;
q = q + 1;
cout << (unsigned long)(q) << endl;
cout << (unsigned long)(p) << endl;
p = p + 1 ;
cout << (unsigned long)(p) << endl;

Assuming it's the pointer arithmetic you have problems with, let my try to to show how it's done in a more "graphical" way:
Lets say we have a pointer variable ptr which points to an array of integers, something like
int array[4] = { 1234, 5678, 9012, 3456 };
int* ptr = array; // Makes `ptr` point to the first element of `array`
In memory it looks something like
+------+------+------+------+
| 1234 | 5678 | 9012 | 3456 |
+------+------+------+------+
^ ^ ^ ^
| | | |
ptr ptr+1 ptr+2 ptr+3
The first is technically ptr+0
When adding one to a pointer, you go to the next element in the "array".
Perhaps now you start to see some similarities between pointer arithmetic and array indexing. And that is because there is a common thread here: For any pointer or array p and valid index i, the expression p[i] is exactly the same as *(p + i).
Using the knowledge that p[i] is equal to *(p + i) makes it easier to understand how an array can be used as a pointer to its first element. We start with a pointer to the first element of array (as defined above): &array[0]. This is equal to the expression &*(array + 0). The address-of (&) and dereference (*) operators cancel out each, leaving us with (array + 0). Adding zero to anything can be removed as well, so now we have (array). And finally we can remove the parentheses, leaving us with array. That means that &array[0] is equal to array.

You do it right, if you want to print the decimal representation of the addresses your pointers point to.
If you wonder, why the results are such, you need to learn pointer arithmetic. If you add 1 to any pointer, it's address will be increased by sizeof(<type>), where type is the type of the variable your pointer points to.
So that, if you have a pointer to int and increment it, the address will be increased by sizeof(int), which is, most likely, four.

Related

Pointer Arithmetic (adding ints to arrays)

So I read online that if you have an array like
int arr[3] = {1,2,3}
I read that if you take (arr+n) any number n it will just add sizeof(n) to the address so if n is an integer(takes up 4 bytes) it will just add 4 right? But then I also experimented on my own and read some more stuff and found that
arr[i] = *(arr+i) for any i, which means it's not just adding the sizeof(i) so how exactly is this working?
Because obviously arr[0] == *(arr+0) and arr[1] == *(arr+1) so it's not just adding sizeof(the number) what is it doing?
I read that if you take (arr+n) any number n it will just add sizeof(n) to the address
This is wrong. When n is an int (or an integer literal of type int) then sizeof(n) is the same as sizeof(int) and that is a compile time constant. What actually happens is that first arr decays to a pointer to the first element of the array. Then sizeof(int) * n is added to the pointers value (because elements type is int):
1 2 3
^ ^
| |
arr arr+2
This is because each element in the array occupies sizeof(int) bytes and to get to memory address of the next element you have to add sizeof(int).
[...] and read some more stuff and found that arr[i] = *(arr+i)
This is correct. For c-ararys arr[i] is just shorthand way of writing *(arr+i).
When you write some_pointer + x then how much the pointer value is incremented depends on the type of the pointer. Consider this example:
#include <iostream>
int main(void) {
int * x = 0;
double * y = 0;
std::cout << x + 2 << "\n";
std::cout << y + 2 << "\n";
}
Possible output is
0x8
0x10
because x is incremented by 2* sizeof(int) while y is incremented by 2 * sizeof(double). Thats also the reason why you get different results here:
#include <iostream>
int main(void) {
int x[] = {1,2,3};
std::cout << &x + 1 <<"\n";
std::cout << &x[0] + 1;
}
However, note that you get different output with int* x = new int[3]{1,2,3}; because then x is just a int* that points to an array, it is not an array. This distinction between arrays and pointers to arrays causes much confusion. It is important to understand that arrays are not pointers, but they often do decay to pointers to their first element.

Multidimensional array

The question is to find the output of the follwing program.
This came out in my test and i got wrong. My answer was 4, 7, 10. The answer is 4,8,12 but i need an explanation on how it works
#include<iostream>
using namespace std;
int main ()
{
int number = 4;
int array[] = {7,8,9,10,11,12,13};
int *p1 = &number ;
int *p2 = array;
int *p3 = &array[3];
int *q[] = {p1,p2,p3};
cout << q[0][0] << endl ;
cout << q[1][1] << endl ;
cout << q[2][2] << endl ;
return 0;
}
What you have is not a multi-dimensional array (C++ doesn't really have it). What you have is an array of pointers. And pointers can be indexed like arrays.
In "graphic" form the array q looks something like this:
+------+------+------+
| q[0] | q[1] | q[2] |
+------+------+------+
| | |
v | v
+------+ | +-----+----------+----------+-----+
|number| | | ... | array[3] | array[4] | ... |
+------+ | +-----+----------+----------+-----+
v
+----------+----------+-----+
| array[0] | array[1] | ... |
+----------+----------+-----+
Some notes:
What most people call multidimensional arrays are actually arrays of arrays. Much like you can have an array of integers, or like in the case of q in your code an array of pointers to integers, one can also have an array of arrays of integers. For more "dimensions" it's just another nesting of arrays.
As for why pointers and arrays both can be indexed the same way, it's because for any array or pointer a and (valid) index i, the expressions a[i] is equal to *(a + i). This equality is also the reason you can use an array as a pointer to its first element. To get a pointer to an arrays first element one can write &a[0]. It's equal to &*(a + 0), where the address-of and dereference operators cancel each other out leading to (a + 0) which is the same as (a) which is the same as a. So &a[0] and a are equal.
q[0] is in fact p1, q[1] is in fact p2 and q[2] is p3.
Now p1 is the address of number so p1[0] is simply the value of number which you correctly computed to be 4.
p2 points to array so p2[1] is the same as array[1] which is the second element in array ot 8.
p3 points to the subarray of array starting from position 3. So p3[2] is the same as array[3 + 2] = array[5] = 12.

C++ pointer to char arithmetic

If I add 1 to a pointer, the actual value added will be the size of the type that the pointer points to right? For example:
int* num[5];
cout << *num << ", " << *(num + 2) << endl;
This will print the value stored at num[1] and at num[2],
so num + 2 is actually num + 2*sizeof(int) if I'm not wrong.
Now, if I initialize an array of pointers to char to string literals, like this one:
char* ch[5] =
{
"Hi",
"There",
"I,m a string literal"
};
This can be done because a string literal like "hi" represents the address of its first character, in this case 'h'. Now my question is how can I write something like:
cout << *(ch + 2);
and get "I,m a string literal" as the output?
Since the pointer points to char, shouldn't adding 2 to the pointer actually be (ch + 2*sizeof(char)) ? giving me the output 'There' ?
Does it have something to do with cout? Does cout search the memory of the pointed to values to see if it finds '\0's recognizing the contents of the pointed to values as strings and then modifying pointer arithmetic? But then adding 1 to a pointer to char pointing to strings would mean adding different number of bytes (instead of the size of a char) everytime, since a string can be any size. Or am I totally wrong? I'm sorry I am new to C++, and programming in gerenal.
The array isn't storing chars, it's storing char *s. Hence saying ch + 2 will be equivalent to ch + 2*sizeof(char *). You then dereference that, which is pointing to "I'm a string literal".
Your initial example shows the confusion:
int* num[5];
cout << *num << ", " << *(num + 2) << endl;
This is an array of pointers-to-int. Hence, *(num + 2) will be *(num + 2*sizeof(int *)), not 2*sizeof(int). Let's demonstrate this with a small program:
#include <iostream>
int main()
{
int *num[3];
int x, y, z;
x = 1;
y = 2;
z = 3;
num[0] = &x;
num[1] = &y;
num[2] = &z;
std::cout << *(num + 2) << "\n";
}
This will print out a memory address (like 0x22ff28) because it is holding pointers, not values.
In C and C++, arrays and pointers are very similar (many books claim they are exactly the same. This is not -quite- true, but it is true in a lot of situations).
Your first example should be int num[5]. Then *(num + 2) (which is equivalent to num[2]) will be equivalent to *(num + 2*sizeof(int). Hopefully this clears up your confusion somewhat.
"If I add 1 to a pointer, the actual value added will be the size of the type that the pointer points to right?"
There's no guarantee in the C++ Standard that a pointer is the number of the byte of some memory where the pointer points to. If you add an integer n to a pointer, the result is a pointer to the nth next element in that array:
int iarr[10];
int* pi = iarr; // pi points to iarr[0]
int* pi2 = pi+2; // pi2 points to iarr[2]
What you get when you look at, e.g. int repr = (int)pi; is not defined by the C++ Standard.
What will happen on the most popular platforms/implementations, is that
(int)pi2 == ((int)pi) + 2*sizeof(int)
When you have arrays of pointers, the exact same thing happens:
int* piarr[10];
int** ppi = piarr; // ppi points to iarr[0]
int** ppi2 = piarr+2; // ppi2 points to iarr[2]
Note that the type of piarr is array of 10 pointer to int, therefore the elements of that array have the type pointer to int. A pointer to an element of that array consequently has the type pointer to pointer to int.
char* ch[5] is an array of 5 pointers to char.
"Hello" etc. are (narrow) string literals. A (narrow) string literal is an array of n const char, where n is the length of the string plus 1 (for the terminating \0 character). Arrays can be implicitly converted to pointers to the first element of the array, this is what happens here:
char* ch[5] =
{
"Hi",
"There",
"I,m a string literal"
};
The array ch contains three pointer to char. As those have been obtained by converting arrays to pointers, each of them points to the first element of an array of char: The pointer ch[0] (the first element of the array ch) points to the first element of the array "Hi", ch[1] points to the first element of "There" and so on.
Note there's also a conversion involved from const char to char, which is deprecated and should be avoided. The better form would be:
char const* ch[5] =
{
"Hi",
"There",
"I,m a string literal"
};
The expression *(ch + 2) is interpreted as follows:
ch names that array (see above)
ch + 2 implicitly converts ch from array of 3 pointers to char to pointer to pointer to char, a pointer pointing to the first element of the array ch. The type of this expression therefore is pointer to pointer to char.
ch + 2 makes the pointer from the last step now point to the second next element; it pointed to the first element of ch, so it now points to the third element of the array ch.
*(ch + 2) finally, the * dereferences the pointer and "fetches" the object pointed to. The pointer created by ch + 2 points to the 3rd element of the array ch, therefore, this expression resolves into the third element of the array ch. The type of the expression now is pointer to char.
The result of the expression is passed to std::cout::operator<<. As the type of the expression is pointer to char, cout will print that string: the third element of the array ch.
In C, a character is represented by the datatype char. It can hold any ASCII character and it ranges from 0 to 255. Moreover it uses a single byte of size.
A string, however, is represented by char*, which technically is an array of chars. There's a difference. A char is not the same as a char*. The former stores a single character, and the latter stores a memory direction which corresponds to the offset of the string.
Now, in your example, ch is not a char* but a char**. This is, it is an array of an array of chars, or better said, an array of strings. If we dereference ch once, as in *ch, we will get the first string: Hi. If we dereference it twice, as in **ch, we will get the first character of the first string: H. So, we can start working with pointer arithmetics!
cout << *(ch + 2) will output I,m a string literal
cout << **(ch + 1) will output T (first character of second string)
cout << *(*ch + 1) will output i (second character of first string)
Keep on working with these examples to understand better how characters and strings are output! It's all about pointer arithmetics!
Does it have something to do with cout?
No:
const char* cstrings[5] =
{
"Hi",
"There",
"I,m a string literal"
};
const char** x = cstrings + 2;
cout << *x << endl;
.
.
But what can be confusing is that the << operator works differently when given a pointer to a cstring--instead of outputting the address, it outputs the string. Here is an example:
int x = 10;
int* pint = &x;
const char* pstr = "hello";
cout << pint << endl << pstr << endl;
--output:--
0x7fff5fbff85c //hexidecimal string representation of an integer
hello
Since the pointer points to char,
1) The literal strings are stored in your array as pointers. That's why the type of the array is pointer.
2) Pointers are adresses in memory, which are just integers.
3) So your array of pointers is really an array of integers.

c++ navigate through array by moving pointer

In the following I expected 13 to be printed.
I wanted to move arr (which is a pointer to the memory, where int values from array are stored, if i understand everything right) by the size of one array member, which is int.
Instead 45 is printed. So instead making one array-member-wide jump the 5th Array member is retrieved. Why?
int arr[] = {1,13,25,37,45,56};
int val = *( arr + 4 ); //moving the pointer by the sizeof(int)=4
std::cout << "Array Val: " << val << std::endl;
Your assumption is wrong. It moves the pointer 4 elements ahead, not 4 bytes ahead.
*(arr + 4) is like saying in that logic *(arr + 4 * sizeof (arr [0])).
The statement *(arr + 4) is equivalent to arr [4]. It does make for some neat syntax, though, as *(4 + arr) is equally valid, meaning so is 4 [arr].
Your behaviour could be achieved through the following example:
#include <iostream>
int main()
{
int a[3] = {65,66,67};
char *b = reinterpret_cast<char *>(a);
std::cout << *(b + sizeof (int)); //prints 'B'
}
I wouldn't recommend using reinterpret_cast for this purpose though.
arr + 4 will give you 4 items on from the start address of the array, not 4 bytes. That's why you get 45 which is the zeroth item plus 4.
It is performing pointer arithmetic. See this: http://www.eskimo.com/~scs/cclass/notes/sx10b.html
arr is your array and this decomposes to the first element arr[0] which will be 1, then you + 4 to it which moves the pointer by 4 elements arr[4] so it is now pointing to 45.

Pointer to pointer array understanding problem

This is probably a stupid question, but I don't understand why this works:
int** test = new int*[7];
int x = 7;
*(test+1) = &x;
cout << (**(test+1));
test is a pointer to a pointer right? The second pointer points to the array, right?
In my understand I would need to dereference the "test" pointer first to get to the pointer that has the array.
(*test) // Now I have int*
*((*test) + 1) // to access the first element.
Where is my faulty thinking?
int** test = new int*[7];
+------++------++------++------++------++------++------+
| int* || int* || int* || int* || int* || int* || int* |
+------++------++------++------++------++------++------+
is the equivalent of an array with int pointers:
int* test[0]
int* test[1]
...
int* test[6]
this
int x = 7;
*(test+1) = &x;
+------++------++------++------++------++------++------+
| int* || &x || int* || int* || int* || int* || int* |
+------++------++------++------++------++------++------+
is the same as
int x = 7;
test[1] = &x
so now one of the pointers in your original array is pointing the memory location of x
cout << (**(test+1));
is the same as
cout << *test[1]
which is the value of x (==7) and which both test[1] and &x point to.
Is your misunderstanding that you think you have created a pointer to an array of 7 int? You haven't. You actually have created an array of 7 pointers to int. So there is no "second pointer" here that would point to an array. There is just one pointer that points to the first of the 7 pointers (test).
And with *test you get that first pointer which you haven't initialized yet, though. If you would add 1 to that, you would add 1 to some random address. But if you add 1 to test you get a pointer that points to the second pointer of the array. And dererencing that you get that second pointer, which you did initialize.
What you describe would be achieved by a different syntax
typedef int array[7];
array* test = new int[1][7];
// Note: "test" is a pointer to an array of int.
// There are already 7 integers! You cannot make it
// point to an int somehow.
*(*test + 1) = 7;
int *p1 = *test
int i1 = *(p1 + 1); // i1 is 7, second element of the int[7]
delete[] test;
Without using the typedef, this looks like the following
int(*test)[7] = new int[1][7];
That is, you have created a one-element array, where the element-type of that is a 7-element array of int. new gives you a pointer back to that array. Note that the parenthesis is important: The * has less precedence than the [7], so otherwise this would be taken as an array of 7 pointer to integers.
Suppose that
test[0] = 0x12345678; // some pointer value
test[1] = 0x23456789; // some pointer value
*test = 0x12345678;
*test + 1 is now 0x12345678 + 1 = 0x12345679;
* or dereference operator has higher precedence than binary +). So the expression is evaluated in that order.
However what you wanted for is to get to test[0] = 0x23456789;
So the correct expression to get to test[1] = (*(test + 1))
In general arr[i] is *(arr + i)
EDIT 2:
given
int buf[10] = {0, 1, 2};
int *p = buf;
buf[0] == p[0] == *(p + 0) equal to 0.
Note that it is perfectly fine to use array access syntax with the lvalue expression p even if it is not an array type. In fact the expression buf[0] is internally translated by the compiler to *(buf + 0) as well.
The expression *(test + 1) is equivalent to test[1], so your code could be rewritten thus:
int** test = new int*[7];
int x = 7;
test[1] = &x;
cout << *test[1];
Since test[1] obviously points to x, *test[1] is 7.
Just to be clear, the expression **(test + 1) is simply equivalent to *(*(test + 1)), which is in turn equivalent to *test[1].