Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
So I'm new to programming and I want to understand the use of pointers in this program that my professor made.
#include <iostream>
using namespace std;
typedef int* IntPtr;
int main()
{
IntPtr p;
int a[10];
int i;
for(i = 0; i<10; i++)
a[i] = i;
p = a;
for(i = 0; i<10; i++)
cout << p[i]<< " ";
cout << endl;
}
Output:
0 1 2 3 4 5 6 7 8 9
According to what I read 'p = a' will pass the address of the first element of the array to 'p'. So I assume that the output would be all zeros. But when it printed it has the same elements as the array 'a'. It's like it passed the address of all the elements of a to p. Can someone please explain why. sorry if I can't explain the problem well but I hope you get my point.
Accessing an element through a[i] or p[i] with a being an array type and p being a pointer type is called the subscript operator, and you can read about its semantics, for example, in built in subscript operator:
...
The expression E1[E2] is exactly identical to the expression *(E1 + E2)
This means that p[i] is the same as *(p + i), i.e. it dereferences the value at memory address (p+i), whereas i is counted correctly using sizeof(int) since p is a pointer to int. And if p points to a, this is exactly the same as a[i], which again is the same as *(a+i), where a decays to a pointer to the first element in array a.
Hope it helps.
And I hope that your professor teaches the meaning of pointers, memory layout, dereferencing, and so on. IMHO, being confident with pointers and pointer arithmetic is a matter of months (actually years) rather than a matter of a "lesson".
It's actually a shame that students aren't explained how memory management works anymore...
If you allocate something, it physically ends up as a continuous piece of memory. That is: if you allocate an array, it's a sequence of bytes in one continuous block of memory.
Pointers are nothing more than a small block of memory (usually 4 or 8 bytes) that contains the address of something else. E.g. it points to data.
The array in this case is a sequence of bytes, and because int has 4 bytes, it's 40 bytes. Dereferencing an element in the array means reading integer at index X. (in other words: reading the 4 bytes from X*4 up to but not including (X+1)*4 -- or more precise: [X*4, (X+1)*4>).
Using a pointer means reading the contents that the address points to. In this case the pointer contains the address of the first element of the array, so reading *p means reading the first 4 bytes of the array. It's a synonym for p[0].
This basically works, because the data in the array is stored continuously and because no data is copied. So, if you write a[2] = 2, it simply overwrites bytes 2*4 to (2+1)*4 (more precise: [2*4, (2+1)*4>) in your memory block that is named your array. It doesn't make a copy, change the address in p or anything else.
PS: One important detail to note is that in C++ allocation of things like integer arrays doesn't mean setting everyting to 0. It just allocates a slab of memory with the right type; nothing more.
Related
This question already has answers here:
Why a pointer + 1 add 4 actually
(6 answers)
Closed 5 years ago.
I have been learning about using pointers with arrays. If I was to write this simple code:
string Array[3] = {"one", "two", "three"};
string *pArray = Array;
pArray = pArray + 1;
std::cout << *pArray << std::endl;
The output is 'two'
Can someone explain to me the workings of this? Why does the +1 change the position of the pointer to where "two" is in the array? I'd expect the +1 to be concatenated onto the end of the string pointer so I'd end up with something like '0x61feb01'.
How does the compiler know to increment the array and not just add a 1 on to the end of the pointer string memory location?
Why is adding an int to a string different here?
Thanks.
I think when you add "1" to your pointer, this "1" is not treated as an integer number in the process of addition. Notice that pointer is an address, now, when you add 1 to your pointer it becomes: the address it currently is+ONE COMPLETE SIZE of a string type. So for example if your string type takes 8 Bytes you're moving 8 Bytes forward in the memory and not 1 Bytes!
As to why "two" printed you should know that array elements are held in continuous groups of bytes in the memory thus when you add to the address of one of the elements you can get to the other elements. Array names are nothing but pointers themselves except that they are fixed pointers(you can't change their addresses). E.g. In (int myArr[10]) the name "myArr" is a pointer that points to the(has the address of the) first part in the ram that holds the first element and then using pointer arithmetic just as you've done in the above example of yours you can access the rest of the elements either.
As an ending note, these two are equal in this example array: (myArr[i]==*(myArr+i)), if you put 0 here instead of i, you get (myArr[0]==*myArr) which is exactly what I said earlier. I hope it helps.
This question already has answers here:
Why can't we use double pointer to represent two dimensional arrays?
(6 answers)
Closed 6 years ago.
int main()
{
matrix[2][4] = {{11,22,33,99},{44,55,66,110}};
int **ptr = (int**)matrix;
printf("%d%d",**matrix,*ptr);
}
But when a 2-d array is passed as a parameter it is typecasted into (*matrix)[2] ..
what type does the compiler store this array as... is it storing as a 2-d array or a double pointer or an pointer to an array .. If it is storing as an array how does it interprets differently at different situations like above. Please help me understand.
Is 2d array a double pointer?
No. This line of your program is incorrect:
int **ptr = (int**)matrix;
This answer deals with the same topic
If you want concrete image how multidimensional arrays are implemented:
The rules for multidimensional arrays are not different from those for ordinary arrays, just substitute the "inner" array type as element type. The array items are stored in memory directly after each other:
matrix: 11 22 33 99 44 55 66 110
----------- the first element of matrix
------------ the second element of matrix
Therefore, to address element matrix[x][y], you take the base address of matrix + x*4 + y (4 is the inner array size).
When arrays are passed to functions, they decay to pointers to their first element. As you noticed, this would be int (*)[4]. The 4 in the type would then tell the compiler the size of the inner type, which is why it works. When doing pointer arithmetic on a similar pointer, the compiler adds multiples of the element size, so for matrix_ptr[x][y], you get matrix_ptr + x*4 + y, which is exactly the same as above.
The cast ptr=(int**)matrix is therefore incorrect. For once, *ptr would mean a pointer value stored at address of matrix, but there isn't any. Secondly, There isn't a pointer to matrix[1] anywhere in the memory of the program.
Note: the calculations in this post assume sizeof(int)==1, to avoid unnecessary complexity.
No. A multidimensional array is a single block of memory. The size of the block is the product of the dimensions multiplied by the size of the type of the elements, and indexing in each pair of brackets offsets into the array by the product of the dimensions for the remaining dimensions. So..
int arr[5][3][2];
is an array that holds 30 ints. arr[0][0][0] gives the first, arr[1][0][0] gives the seventh (offsets by 3 * 2). arr[0][1][0] gives the third (offsets by 2).
The pointers the array decays to will depend on the level; arr decays to a pointer to a 3x2 int array, arr[0] decays to a pointer to a 2 element int array, and arr[0][0] decays to a pointer to int.
However, you can also have an array of pointers, and treat it as a multidimensional array -- but it requires some extra setup, because you have to set each pointer to its array. Additionally, you lose the information about the sizes of the arrays within the array (sizeof would give the size of the pointer). On the other hand, you gain the ability to have differently sized sub-arrays and to change where the pointers point, which is useful if they need to be resized or rearranged. An array of pointers like this can be indexed like a multidimensional array, even though it's allocated and arranged differently and sizeof won't always behave the same way with it. A statically allocated example of this setup would be:
int *arr[3];
int aa[2] = { 10, 11 },
ab[2] = { 12, 13 },
ac[2] = { 14, 15 };
arr[0] = aa;
arr[1] = ab;
arr[2] = ac;
After the above, arr[1][0] is 12. But instead of giving the int found at 1 * 2 * sizeof(int) bytes past the start address of the array arr, it gives the int found at 0 * sizeof(int) bytes past the address pointed to by arr[1]. Also, sizeof(arr[0]) is equivalent to sizeof(int *) instead of sizeof(int) * 2.
In C, there's nothing special you need to know to understand multi-dimensional arrays. They work exactly the same way as if they were never specifically mentioned. All you need to know is that you can create an array of any type, including an array.
So when you see:
int matrix[2][4];
Just think, "matrix is an array of 2 things -- those things are arrays of 4 integers". All the normal rules for arrays apply. For example, matrix can easily decay into a pointer to its first member, just like any other array, which in this case is an array of four integers. (Which can, of course, itself decay.)
If you can use the stack for that data (small volume) then you usually define the matrix:
int matrix[X][Y]
When you want to allocate it in the heap (large volume), the you usually define a:
int** matrix = NULL;
and then allocate the two dimensions with malloc/calloc.
You can treat the 2d array as int** but that is not a good practice since it makes the code less readable. Other then that
**matrix == matrix[0][0] is true
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I'm studying C++ using a few books, trying to learn SDL along side it. I understand that pointers "point" to a variable's memory address, and that they can be used to "reference" variables. But I don't understand their purpose? And how to use them properly?
I have a few examples from the book (I've added under the code that confuses me):
#include <iostream>
int main(void)
{
char string[6] = "Hello";
char* letter = string;
letter += 3;
OK, so there's a char pointer called 'letter' that points to the memory address of string. Then somehow we use the += operator on the pointer? How? What's going add? What are we adding the 3 to?
*letter = 'p';
And now here we use '*letter' instead of 'letter' - this means it's dereferenced, right? What does this actually DO?
string[4] = '!';
std::cout << string << '\n';
system("PAUSE");
return 0;
}
The rest of the code I understand.
Thanks for any answers!
George
EDIT: so let me get this straight - dereferencing a pointer (e.g. *pointer = 2;) is used to change the value of the variable (or array position, for that matter) when you want to?
EDIT 2: thanks to everybody's answers I almost completely understand the code I used as an example - however, I am still unsure as to the use of '&' (ampersand) in the context of pointers, and how/why they're used.
In this definition
char* letter = string;
letter is set to the address of the first element of character array string.
So *letter has value 'H'.
Let consider for example statement
++letter;
This statement "moves" the pointer to point to the next element of string. That is now the pointer points to the second element of string. Now the value pf *letter is 'e' because letter points to the second element.
Applying three times operator ++ as for example
++letter; ++letter; ++letter;
is equivalent to
letter += 3;
that is the pointer was moved three times and now it points to the second 'l' in string.
This statement
*letter = 'p'
will replace 'l' with 'p' and you will get that string now looks as
"Helpo"
After executing statement
string[4] = '!';
string contains
"Help!"
Instead of
string[4] = '!';
you could write
++letter;
*letter = '!';
Or you could combine these two statements in one statement
*++letter = '!';
EDIT: 'pointer' contains address of an object. When you write *pointer you access directly the object itself so *pointer = 2 change the object pointed by 'pointer'.
Also you should understand that if for example you have
int a[10];
int *p = a;
and let assume that the value of p (the address stored in p) is 4. Then expression ++p or p + 1 means that the pointer was "moved" to the next element of the array. It means that new value of p is not 5. The new value of p is p + sizeof( int ) that is 8 provided that sizeof( int ) is equal to 4.
In your example sizeof( char ) is always equal to 1 according to the C++ Standard.
You need a start from understanding pointers from beginning.
char string[6] = "Hello"; //string an array of 6 characters including null char
char* letter = string; //letter pointer pointing to string array,stores first char address
letter += 3; // Letter pointer in incremented by 3 char. Now it points to 4th char of string
*letter='p'; //replacing 4th char of string by p
cout<<letter; //prints "po";
Notes to help you
What are the barriers to understanding pointers and what can be done to overcome them?
Incrementing a pointer by an integer value (explained with an example):
Suppose you have int* x pointing to memory address 1000, and you increment it by 3: x += 3.
Variable x will now point to memory address 1000 + sizeof(int).
The size of int depends on your compiler; let's assume it is 4 bytes on your system.
So variable x is pointing to memory address 1012 (1000+3*4).
Now, suppose you use x in order to read the value at the memory address pointed by x:
int y = *x;
During runtime, the CPU will read 4 bytes from the memory address pointed by x, and store them into variable y, so that y will then contain the same value as the one stored in address range 1012-1015.
Then somehow we use the += operator on the pointer? How? What's going add? What are we adding the 3 to?
letter is in fact pointing to the first element of the string Hello. By adding 3 to it letter will point to the element 3 of the string (4th element).
And now here we use '*letter' instead of 'letter' - this means it's dereferenced, right? What does this actually DO?
Defreference means you are retrieving the value stored at the location letter points to.
ereferencing a pointer (e.g. *pointer = 2;) is used to change the value of the variable (or array position, for that matter) when you want to?
By doing *pointer = 2; you are storing 2 to the location pointer points to, ie, changing the value of the variable..
This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 10 years ago.
I have the below code:
int* d = (int*) malloc(100 * sizeof(int));
cout<<"size of d which is pointer is: " << sizeof(d)<<endl;
I know that sizeof outputs 4 as d is a ptr. But, how can I find the sizeof the entire array using sizeof
You cannot - sizeof is a compile time operation and hence not dynamic.
As you are using c++ use std::vector instead. Otherwise create a structure to store both the pointer and the size of the array. Pass that around instead.
The pointer gives you the place in memory where your data is stored which is why you can't get it's size only from that information.
It's analogous to knowing how big my house is from knowing my address (without prior knowledge or the use of tools like Google Maps)
The direct ans. is no you can't but you can try this :
int x[]={1,2,3,4};
int *ptr=x;
decltype(sizeof(*ptr)) size=0;
while(*ptr<5){
size =size+sizeof(*ptr);
ptr++;
}
cout<<"Size is : "<<size;
Output:
Size is:16
You could argue that you already know the size of the entire array using sizeof - you've got it in your original malloc call - 100 * sizeof(int). Although the malloc machinery must know the amount of memory associated with the pointer internally (it needs it for a corresponding free call), and apparently some implementations provide functions to return this information, as far as I know there is not implementation-independent and portable way of doing this without handling it yourself.
I've been studying C++ for a test and I am currently stuck with pointer arithmetic.
The basic problem is the following:
int numColumns = 3;
int numRows = 4;
int a[numRows][numColumns];
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 4;
a[1][1] = 5;
a[1][2] = 6;
a[2][0] = 7;
a[2][1] = 8;
a[2][2] = 9;
a[3][0] = 10;
a[3][1] = 11;
a[3][2] = 12;
for (int i=numColumns-1; i>-1;i--)
{
cout << a[numRows-1][i] << endl;
}
A very simple program which prints the lower "row of the matrix". i.e. 12,11,10.
Now I am trying to do the equivalent with a int*.
What I have been told by my classmates is to think it like this:
array[i][j] == p[numColumns*i+j]
If that is correct, shouldn't the following be equivalent to what I'm looking for:
int* p = reinterpret_cast<int*> a;
for (int i=numColumns-1; i>-1;i--)
{
cout << p[numColumns*(numRows-1)+i] << endl;
}
Thanks.
int array[3][5] is NOT an abstraction (in the C++ language) for int array[3*5]. The standard says that a 2 dimensional array (and N-dimensional arrays in general) are arrays of arrays. That array[3][5] is an array of three elements, where each element is an array containing 5 elements (integers in this case). C++'s type system does make that distinction.
According to the C++ standard, and array T array[N] is a contiguous block of memory containing the N elements of type T. So that means that a multidimensional array, let's say int array[3][5] will be a continuous block of memory containing 3 int[5] arrays, and each int[5] array is a contiguous block of 5 ints.
On my machine, the memory ends up laid out exactly as you would expect - identical to int array[3*5]. The way the memory is treated is different however, due to the type system (which distinguishes between int[] and int[][]). This is why you need to use a reinterpret_cast which essentially tells your compiler "take this memory and without doing any conversion, treat it like this new type".
I'm not completely sure if this memory layout is guaranteed however. I couldn't find anything in the standard stating that arrays can't be padded. If they can be padded (again, I'm not sure) then it's possible that the int[5] array is not actually 5 elements long (a better example would be char[5], which I could see being padded to 8 bytes).
Also there is an appreciable difference between int* and int** since the latter doesn't guarantee contiguous memory.
EDIT: The reason that C++ distinguishes between int[3*5] and int[3][5] is because it wants to guarantee the order of the elements in memory. In C++ int[0][1] and int[0][2] are sizeof(int) apart in memory. However in Fortran, for example, int[0][0] and int[1][0] are sizeof(int) apart in memory because Fortran uses column major representation.
Here's a diagram to help explain:
0 1 2
3 4 5
6 7 8
Can be made into an array that looks like {0,1,2,3,4,5,6,7,8} or an array that looks like: {0,3,6,1,4,7,2,5,8}.
Hint: in your original code, the type of a is more similar to int**, so you shouldn't cast it to int*. It is a pointer to pointer to something.
If you want to access it like an 1-D array, then a has to be defined as an 1-D array as well.
#rwong: Really? I thought that multi-dimensionals arrays were just an "abstraction" for us, since the following are equivalent:
int array[3][5];
int array[3*5];
Anyways, I detemined what was wrong. As usual it was not my code, but copy-pasting someone's code and working from there.
What I had was this:
for(int i=numRows-1; i>-1 ;i++)
{
cout << p[numColumns*numRows-1+i] << endl;
}
Is funny because I did not copy-paste my code from VS, but actually wrote it from scratch to "illustrate" my error.
Lesson to be learnt here ;)
Edit: I'm still not sure about what rwong explained here. Would anyone care to elaborate?
Another way to think about it: since a is similar to an int**, is there a part of a that's similar to an int*?