Let's say i have a 2 D array int m[3][4]
If the typedef is defined as
typedef int array[4];
array *ptr = m;
What does this mean? Is it pointer to array of 4 elements. Or array of 4 pointers?
When we cout << ptr or cout << *ptr, It prints the same address. How is that possible?
ptr is pointer to an array of four elements of type int. m is an array of 3 elements of type (of array of four elements of type int). To give you a picture - m is an array of 3 elements of type array. And that is the reason when ptr is initialized to m - there is no problem because 'm' being an array is implicitly converted to pointer to first element in that array.
ptr is pointer to an array of elements. So that pointer is printed. And when *ptr is used - you get an array which again get's implicitly converted to pointer to the first element of the array, which again is the same starting point - so you get the same value.
As everything starts at the same point you are getting the same value. Thing will start differentiating when one does ++ on pointers. I will leave you with that.
Check out the clockwise/spiral rule. After reading this you can read the declaration as being a pointer to the type-alias array, in other words a pointer to an array of four integers.
As per "clockwise/spiral rule" ptr is a pointer to array of 4 int.
Related
Here is the context:
int *t[10];
int n;
I am being told that t-n is of the type int**.
I don't exactly get what int** means, is it a pointer of a pointer? Why would the subtraction of a table of pointers - int would give a pointer of pointer of an int? When we refer to *t[0] do we refer to int* p to the pointer itself because it is an element of the table or do we implicitly need a pointer to point at the slot than have the pointer point to the another place?
Thanks in advance for explaining this to me.
I don't exactly get what int** means, is it a pointer of a pointer?
Yes.
int = integer
int * = pointer-to-integer
int ** = pointer-to-(pointer-to-integer)
int *** = pointer-to-(pointer-to-(pointer-to-integer))
(and so on)
Why would the subtraction of a table of pointers - int would give a
pointer of pointer of an int?
Because in C (and C++), an array decays into a pointer to the first item when necessary. For example, int *t[10] is an array of 10 pointer-to-int items. t can decay into a pointer to t[0], ie a pointer-to-(pointer-to-int), int **. That pointer can then be used for pointer arithmetic (like subtraction).
So, subtracting n from t would give you an int ** that is pointing n items "before" the beginning of your 10-item array (which BTW would not be a safe pointer to use, unless n was zero or a small negative number, since it would be pointing outside the valid bounds of the array's memory).
When we refer to *t[0] do we refer to int* p to the pointer itself
because it is an element of the table or do we implicitly need a
pointer to point at the slot than have the pointer point to the
another place?
I'm not sure I understand this question. Since t[10] is an array of 10 pointers (i.e. 10 int *'s), that means that t[0] is a single item in that array and therefore has type int *. Therefore *t[0] dereferences the first pointer in the array, yielding the actual int value that the pointer is pointing to.
what int** means
It's the type of a pointer to a pointer to an int. If you dereference a variable t of this type (like this: *t), you get a pointer to an int. If you dereference it twice (like this: **t), you get an int.
If you have TYPE a[N];, the array expression a, if evaluated, produces a pointer of type T *, pointing to a[0]. This is sometimes called C's array-to-pointer "decay" rule.
If TYPE is int *, as in your case, then TYPE * is int **.
Since your array is of int * pointers, the pointer which indexes into the array is a necessarily pointer to that element type.
I was wondering how *(&array + 1) actually works. I saw this as an easy way to calculate the array length and want to understand it properly before using it. I'm not very experienced with pointer arithmetic, but with my understanding &array gives the address of the first element of the array. (&array + 1) would go to end of the array in terms of address. But shouldn't *(&array + 1) give the value, which is at this address. Instead it prints out the address. I would really appreciate your help to get the pointer stuff clear in my head.
Here is the simple example I'm working on:
int numbers[] = {5,8,9,3,4,6,1};
int length = *(&numbers + 1) - numbers;
(This answer is for C++.)
&numbers is a pointer to the array itself. It has type int (*)[7].
&numbers + 1 is a pointer to the byte right after the array, where another array of 7 ints would be located. It still has type int (*)[7].
*(&numbers + 1) dereferences this pointer, yielding an lvalue of type int[7] referring to the byte right after the array.
*(&numbers + 1) - numbers: Using the - operator forces both operands to undergo the array-to-pointer conversion, so pointers can be subtracted. *(&numbers + 1) is converted to an int* pointing at the byte after the array. numbers is converted to an int* pointing at the first byte of the array. Their difference is the number of ints between the two pointers---which is the number of ints in the array.
Edit: Although there's no valid object pointed to by &numbers + 1, this is what's called a "past the end" pointer. If p is a pointer to T, pointing to a valid object of type T, then it's always valid to compute p + 1, even though *p may be a single object, or the object at the end of an array. In that case, you get a "past the end" pointer, which does not point to a valid object, but is still a valid pointer. You can use this pointer for pointer arithmetic, and even dereference it to yield an lvalue, as long as you do not try to read or write through that lvalue. Note that you can only go one byte past-the-end of an object; attempting to go any further leads to undefined behaviour.
The expression &numbers gives you the address of the array, not the first member (although numerically they are the same). The type of this expression is int (*)[7], i.e. a pointer to an array of size 7.
The expression &numbers + 1 adds sizeof(int[7]) bytes to the address of array. The resulting pointer points right after the array.
The problem however is when you then dereference this pointer with *(&numbers + 1). Dereferencing a pointer that points one element past the end of an array invokes undefined behavior.
The proper way to get the number of elements of an array is sizeof(numbers)/sizeof(numbers[0]). This assumes that the array was defined in the current scope and is not a parameter to a function.
but with my understanding &array gives the address of the first element of the array.
This understanding is misleading. &array gives the address of the array. Sure, the value of that address is the same same as the first element, but the type of the expression is different. The type of the expression &array is "pointer to array of N elements of type T" (where N is the length that you're looking for and T is int).
But shouldn't *(&array + 1) give the value, which is at this address.
Well yes... but it's here that the type of the expression becomes important. Indirecting a pointer to an array (rather than pointer to an element of the array) will result in the array itself.
In the subtraction expression, both array operands decay into pointer to first element. Since the subtraction uses decayed pointers, the unit of the pointer arithmetic is in terms of the element size.
I saw this as an easy way to calculate the array length
There are easier ways:
std::size(numbers)
And in C:
sizeof(numbers)/sizeof(numbers[0])
e.g.
int arr[2][3] = ...
The type of arr[0] is
int (*)[3] // pointer to int[3], which is a pointer.
Or
int[3] // an array whose size is 3, which is an array.
Google tells me nothing about the question.
I know pointer and array are different types(derived types).
Maybe C and C++ treat it differently, I hope to see standard wording.
arr[0] is of type int [3] which is not a pointer.
int (*p)[3] is of type int(*)[3] meaning pointer to an array of 3 elements.
Pointer is not array and array is not pointer.
Now when you pass this 2d array to a function (or any case where decaying occurs) then it decays into pointer to the first element which is int (*)[3].
To be more clear in C 2d array is nothing but array of arrays.
Dissecting
arr is an array each of element of which is again an array with 3 elements.
arr[0] in most of the cases (except sizeof etc) will decay into pointer to first element it contains which is an int*.
arr[0][0] is an int.
At last &arr[0] .. guess what? This is of type int(*)[3].
This question already has answers here:
How come an array's address is equal to its value in C?
(6 answers)
Closed 7 years ago.
As a beginner programmer I am dealing with some simple problems related to Pointers. In the following code I found the value of *a and a are same in hexadecimal. But I can't understand the reason.
#include <stdio.h>
#include <stdlib.h>
main(){
int a[5][5];
a[0][0] = 1;
printf("*a=%p a=%p \n", *a, a);
return 0;
}
Here is the output:
*a=0x7ffddb8919f0 a=0x7ffddb8919f0
An array and its first element have the same address.:)
For this declaration
int a[5][5];
expression a used in the printf call is implicitly converted to the pointer to its first element. Expression *a yields the first element of the array that is in turn a one-dimensional array that also is converted to a pointer to its first element.
Thus expressions a and *a have the same value as expression &a[0][0]
In C and C++ languages values of array type T [N] are implicitly converted to values of pointer type T * in most contexts (with few exceptions). The resultant pointer points to the first element of the original array (index 0). This phenomenon is informally known as array type decay.
printf argument is one of those contexts when array type decay happens.
A 2D array of type int [5][5] is nothing else than an "1D array of 1D arrays", i.e. it is an array of 5 elements, with each element itself being an array of 5 ints.
The above array type decay rule naturally applies to this situation.
The expression a, which originally has array type int [5][5], decays to a pointer of type int (*)[5]. The pointer points to element a[0], which is the beginning of sub-array a[0] in memory. This is the first pointer you print.
The expression *a is a dereference operator applied to sub-expression a. Sub-expression a in this context behaves in exactly the same way as before: it decays to pointer of type int (*)[5] that points to a[0]. Thus the result of *a is a[0] itself. But a[0] is also an array. It is an array of int[5] type. It is also subject to array type decay. It decays to pointer of type int *, which points to the first element of a[0], i.e. to a[0][0]. This is the second pointer you print.
The reason both pointer values are the same numerically is that the beginning of sub-array a[0] corresponds to the same memory location as element a[0][0].
a can be considered a pointer to a pointer to an int (in reality, it's an array of array of int, but close enough).
So a and *a both point to the same address (which happens to be a[0][0]).
*a is still a pointer, and a[0] is the same address as a[0][0].
At: http://www.fredosaurus.com/notes-cpp/arrayptr/26arraysaspointers.html
Under: Pointer addition and element size
There is the following code:
// Assume sizeof(int) is 4.
int b[100]; // b is an array of 100 ints.
int* p; // p is a a pointer to an int.
p = b; // Assigns address of first element of b. Ie, &b[0]
p = p + 1; // Adds 4 to p (4 == 1 * sizeof(int)). Ie, &b[1]
How did "p" in the last line become "4"?
Thanks.
(I assume that you mean "1" in the last line, not "p")
Pointer arithmetic in both C and C++ is a logical addition, not a numeric addition. Adding one to a pointer means "produce a pointer to the object that comes in memory right after this one," which means that the compiler automatically scales up whatever you're incrementing the pointer with by the size of the object being pointed at. This prevents you from having a pointer into the middle of an object, or a misaligned pointer, or both.
because p is pointer to a type with size 4 bytes. + operator on pointers is actually pointer shift. compiler knows the size of pointed type and shifts it by appropriate value
if you change int to short, p will be shifted by 2 bytes
The comment in the code you post it explains it: addition of an integer x to a pointer increases the pointer's value by x multiplied by the sizeof the type it is pointing to.
This is convenient because it doesn't usually make sense to change the pointer in smaller increments - you wouldn't want it to point into the middle of one of the elements.