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.
Related
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.
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 = #
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.
below is the code that I'm trying to run
#include <iostream>
using namespace std;
int foo(int **a){
cout<<*(a+3)<<endl;
return 1;
}
int main(){
int a[2][2] = {{1,2},{3,4}};
std::cout << sizeof(a);
foo((int **)a);
}
when I have four elements in this array, shouldn't the value *(a+3) return a value 4, instead of that its returning an address and when i try to dereference that address (i.e. **(a+3)) i get segfault 11
Actually you are defining an array of arrays of integers. It can decay to a pointer to an array of integers, but it will not decay into a pointe to a pointer of integers.
It will help if you draw the memory layout:
+---------+---------+---------+---------+
| a[0][0] | a[0][1] | a[1][0] | a[1][1] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
If you let it decay into a pointer-to-array-of-integer:
int (*pa)[2] = a;
+---------+---------+---------+---------+
| pa[0] | pa[1] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
Note how sizeof(*pa) = 2 * sizeof(int). Each of these values can decay into a pointer to integer, but never into a pointer to a pointer:
int *p = pa[0];
Anyway, you can cast the decayed pointer-to-array-of-integer into a pointer to integers and access the four values directly:
int *p = (int*)a;
std::cout << p[3] << std::endl;
std::cout << *(p + 3) << std::endl;
The memory will be like this:
+---------+---------+---------+---------+
| p[0] | p[1] | p[2] | p[3] |
+---------+---------+---------+---------+
| 1 | 2 | 3 | 4 |
+---------+---------+---------+---------+
But if you cast it into a int** you will get meaningless values, because in memory there are no pointers, just integers.
A array is not a pointer. Yes it can decay to a pointer that does not mean it is one. If you want to pass a 2d array then you can use
int foo(int a[][2]);
or if you want to take any size array then you can use
template<std::size_t N>
int foo(int a[][N]);
You are dereferencing too far. a already points to the first element in the array. So **a treats the first value in the array as an address instead of a value. Try
foo((int *)a)
When you dereference int** you get int*. However, you are dereferencing a location with a value 4 that is interpreted as int*. That's why cout prints 0x4, because it formats it as an address. Try taking int* as parameter:
#include <iostream>
using namespace std;
int foo(int *a){
cout<<*(a+3)<<endl;
return 1;
}
int main(){
int a[2][2] = {{1,2},{3,4}};
std::cout << sizeof(a);
foo((int *)a);
}
It prints 4 then.
This is just an example of how to fix up this piece of code in particular, and is not the right way of doing things. Also as #rodrigo stated in the comments of his answer, if the size of an int is not equal to the size of its pointer, this is not going to work. I just wanted to show you why you thought it was printing an address - because it is being interpreted as one.
I am trying to use a reference to pointer to int like in below program. But I am not getting the expected output.
Output:
9 5
5 9
Expecting:
9 5
9 5
Code:
#include <iostream>
using namespace std;
void swap (int *& a, int *&b)
{
int *t = a;
a = b;
b = t;
}
int main()
{
int a = 5, b = 9;
int *p = &a;
int *q = &b;
swap (p, q);
cout << *p << " " << *q << endl;
cout << a << " " << b << endl;
return 0;
}
Why is my expectation wrong? I head that reference is nothing just an other name of the target variable.
You swap the pointers, not the values. Your expectation is wrong.
You're swapping the values of the pointers.
Look at this illustration:
First, p is pointing at a, q is pointing at b:
p a
+---+ +---+
+ ------> | 5 |
+---+ +---+
q b
+---+ +---+
+ ------> | 9 |
+---+ +---+
After you swap p and q, q is pointing at a, and p is pointing at b:
q a
+---+ +---+
+ ------> | 5 |
+---+ +---+
p b
+---+ +---+
+ ------> | 9 |
+---+ +---+
But both a and b still have their old values.
In your case, you're swapping the pointers (and not the values). Since you're swapping the pointers, the actual values inside a and b remain unchanged. Hencewhy when you print the value of a, you get 5 and when you print b you get 9.
In general, you are swapping two pointers and not what they point to.
Maybe your function is confusing you as you are calling the values a and b. Your function swaps two pointers such that the first one now points where the second one was pointing, and the second points to where the first was pointing.
p was previously pointing to a and q to b. Now p points to b and q points to a thus your output is 9 5 5 9
There are references in your swap function. These are references to the pointers, so a and b in the function scope become aliases to the parameters passed in, i.e. p and q and thus modify p and q (to point elsewhere).
I head that reference is nothing just a other name of the target
variable
Yes, and target variable in your case is a pointer of the variable, not the variable. Because you're using * in the function declaration. Then, you're swaping pointers not values.
Use one of these ways:
void swap(int &a, int &b)
{
int t=a;
a=b;
b=t;
}
// ...
int a=5,b=9;
swap(a,b);
or
void swap(int *a, int *b)
{
int t=*a;
*a=*b;
*b=t;
}
// ...
int a=5,b=9;
swap(&a,&b);
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.