Up till now I was pretty much sure that
int arr[4][5];
Then arr will decay to pointer to pointer.
But this link proves me wrong.
I am not sure how did I get about arr being pointer to pointer but it seemed pretty obvious to me. Because arr[i] would be a pointer, and hence arr should be a pointer to pointer.
Am I missing out on something.
Yep you are missing out on a lot :)
To avoid another wall of text I'll link to an answer I wrote earlier today explaining multi-dimensional arrays.
With that in mind, arr is a 1-D array with 4 elements, each of which is an array of 5 ints.
When used in an expression other than &arr or sizeof arr, this decays to &arr[0]. But what is &arr[0]? It is a pointer, and importantly, an rvalue.
Since &arr[0] is a pointer, it can't decay further. (Arrays decay, pointers don't). Furthermore, it's an rvalue. Even if it could decay into a pointer, where would that pointer point? You can't point at an rvalue. (What is &(x+y) ? )
Another way of looking at it is to remember that int arr[4][5]; is a contiguous bloc of 20 ints, grouped into 4 lots of 5 within the compiler's mind, but with no special marking in memory at runtime.
If there were "double decay" then what would the int ** point to? It must point to an int * by definition. But where in memory is that int * ? There are certainly not a bunch of pointers hanging around in memory just in case this situation occurs.
A simple rule is:
A reference to an object of type array-of-T which appears in an expression decays (with three exceptions) into a pointer to its first element; the type of the resultant pointer is pointer-to-T.
When you deal with 1D array, array name converts to pointer to first element when passed to a function.
A 2D array can be think as of an array of arrays. In this case int arr[4][5];, you can think arr[] as an array name and when passed to a function then converts to a pointer to the first element of array arr. Since first element of arr is an array, arr[i] is a pointer to ith row of the array and is of type pointer to array of 5 ints.
In general, a 2-dim array is implemented as an array of pointers (which, in a sense, is a pointer to a pointer... a pointer to the first element (i.e., pointer) in the array) When you specify the first index (i.e., arr[x]), it indexes into the array of pointers and gives the pointer to the x-th row. The the second index (i.e., arr[x][y]) gives the y-th int in that row.
In the case of a static declared array (as in your example), the actual storage is allocated as a single block ... in your example, as a single contiguous block of 20 integers (80 bytes, on most platforms). In this case, there IS no array of pointers, the compiler just does the appropriate arithmetic to address the correct element of the array. Specifically, arr[x][y] is equivalent to *(arr + x * 5 + y). This automatically-adjusted-arithmetic only happens in the original scope of the array... if you pass the array to a function, the dimension information is lost (just as the dimension is lost for a 1-dim array), and you have to do the array-indexing calculations explicitly.
To avoid this, do NOT declare the array as static, but as an array of pointers, with each pointer pointed to a 1-dim array, such as in this example:
int arr0[5];
int arr1[5];
int arr2[5];
int arr3[5];
int* arr[4] = { arr0, arr1, arr2, arr3 };
Then, when you pass arr to a function, you can address it as a 2-dim array within the function as well.
Related
After reading some posts on this site, I realized that array in C isn't just a constant pointer as I originaly thought, but is itself a distinct type, but in most cases array "decays" to a constant pointer to the first element of the array. Because of this new information, a question arised in my mind. Suppose we have a two-dimensional A[10][10]. Why is the result of the expression *A a pointer to the first element of the array ? I thought that in this expression, A decays to a constant pointer to the first element of the array A[0][0], and then the application of the indirection should give us the value of the A[0][0], but in fact it still gives us the address of the first element of the array. Certainly, something is wrong with my logic or my understanding of the arrays or pointers, so where do I get it wrong ?
Thanks in advance.
The first element of A is A[0], not A[0][0].
This is because A is an array of ten things. C does not have two-dimensional arrays as a primary type. An array with multiple dimensions is derived or constructed as multiple layers of arrays. To the compiler, the resulting type is still just an array, whose elements happen to be further arrays.
Thus, in *A:
A is converted to a pointer to its first element. That pointer is &A[0], so *A becomes *&A[0].
* and & cancel, so the expression becomes A[0].
A[0] is an array of ten elements, so it is converted to a pointer to its first element, &A[0][0].
*A, or A[0], is itself an array of 10 elements and and array is always expressed by a pointer to its first element. However A[10][10] (let's say an array of ints) is effectively a block of memory holding 100 ints, the 10 of the first row followed by the 10 of the second row and so on. But if the expression *A or A[0] would return an int instead of a ptr to that row, it would be impossible to use the expression A[0][0], right ?
However, because such multidimensional array is a single block of memory, it's also possible to cast it to a pointer and then access it with an expression of this kind :
((int *)A)[iRow * 10 + iCol];
Which is equivalent to the expression :
A[iRow][iCol];
But this if it's possible for a 2D array declared this way :
int main()
{
int A[10][10] = { 0 };
A[9][9] = 9999;
printf("==> %d\n", ((int *)A)[9 * 10 + 9]); //==> 9999
return 0;
}
It is not if the memory is potentially made of separate blocks of bytes (probably requiring several calls to malloc) as with this kind of expressions :
int * A[10]; // or
int ** A;
A decays to a constant pointer to the first element of the array
A[0][0]
No, it does not. Why?
C standard specifies that *(pointer + integer) == pointer[integer] so the *A is an equivalent of *(A + 0) which is A[0]. A[0] will not give you the element A[0][0] only the single dimensional array which will decay to pointer to the first element of the first row of this array.
This question already has answers here:
Is an array name a pointer?
(8 answers)
Closed 5 years ago.
void main()
{
int array[10] = {1,2,3,4,5,6,7};
printf("%p\n",array);
}
Here, the system would allocate a memory in stack equivalent to 10 integers for the array. However, i dont think there is any extra memory allocate for the variable array, i presume array is a mnemonic for human understanding and coding purpose. If that is the case, how does the printf() in the statement - printf("%p\n",array); accept it as though it is a pointer variable?
This confusion becomes more evident as the dimension(s) of the array keeps increasing.
int main()
{
int matrix[2][4] = {{11,22,33,99},{44,55,66,110}};
printf("%p\n", matrix);
printf("%p\n", matrix+1);
printf("%p\n", *(matrix+1));
}
The ouput for one of the program execution was -
0x7ffd9ba44d10
0x7ffd9ba44d20
0x7ffd9ba44d20
So both matrix+1 and *(matrix+1), after indirection outputs the same virtual memory address. I understand why matrix+1 address is what it is displaying but i don't understand why *(matrix+1) is outputting the same address even after indirection!
Well arrays are not pointers. Most of the cases(the exceptions are sizeof,&operator, _alignof etc) - it is converted into (array decaying) pointer to first element.
So here matrix is converted (decay) into pointer to first element - which is int (*)[4] when passed to printf.
Now dissect one by one, matrix+1 will point to the second element of the 2d array which is the 2nd element of the 2d array (That's why they are sizeof(int)*4 times apart.
In the third case they are same, because matrix+1 is of type int (*)[4] and when you dereference it you get int[4] basically the same address as that of before.
There is one thing to keep in mind - with pointers there are two things
It's value
It's type.
Two pointers may have the same value but their type may be different. Here also you saw that.
It (decaying) is mentioned in standard 6.3.2.1p3:-
Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type 'array of type' is converted to an expression with type 'pointer to type' that points to the initial element of the array object and is not an lvalue.
Also you print the address in wrong manner (this is one of the case you would use casting).
printf("%p",(void*)matrix);
To make things a bit more clear:-
matrix is basically an object int[2][4] which decayed in the cases you have shown to int(*)[4]. You might wonder what is it that makes matrix+1
point to the second element of the array - the thing is pointer arithmetic is dicated by thing it points to. Here matrix as decayed into pointer to first element (int(*)[4]) it will move by an size of 4 ints.
Why is it that both the memcpy below produces the same result:
int arr1[5] = {some_data1};
int arr2[5] = {some_data2};
memcpy(&arr1, &arr2, (5 * sizeof(int)));
memcpy(arr1, arr2, (5 * sizeof(int)));
Why doesn't the first memcpy see a double pointer for arr1 and arr2? Is it because the array name is not truly a pointer but rather an identifier for a variable of the "array" type?
Why doesn't the first memcpy see a double pointer for arr1 and arr2?
Bluntly speaking, because it is not a double pointer.
Is it because the array name is not truly a pointer but rather an identifier for a variable of the "array" type?
Absolutely! This happens precisely because arrays are not pointers, despite many misleading similarities shared by the two kinds of C objects.
The behavior is the same because both expressions produce numerically identical void* pointers when passed to memcpy.
Because in C, when a is an array we have this:
(void *) a == (void *) &a
the address of &a (pointer to the array) and of &a[0] (pointer to the first element of the array) is the same, only the type is different.
Duplicate of this question - "The name of an array usually evaluates to the address of the first element of the array, so array and &array have the same value."
In some contexts, when you use an array name it is converted to the address of the array. Passing an array as a function argument is one of those contexts. But using the array with the & operator is not -- it returns the address of the array.
in array, your array variable(arr1 amd arr2) naturally represent base address of the array, you do not need to give &(address of operator).
arr1==&arr1
First I declare an array a with 10 elements. Then I call the function bubbleSort
bubbleSort( a, 10);
where bubbleSort is a function declared as
void bubbleSort(int* const array, const int size)
My question is if "array" is a pointer- which means it stored the address of array a (array= &a [0]) then how can we understand these terms array[1], array[2], array[3]... in the function bubbleSort?
It is the bubble sort program and this part is very confusing for me.
array[1] means, by definition in the C standard, *(array+1). So, if array is a pointer, this expression adds one element to the pointer, then uses the result to access the pointed-to object.
When a is an array, you may be used to thinking of a[0], a[1], a[2], and so on as elements of the array. But they actually go through the same process as with the pointer above, with one extra step. When the compiler sees a[1] and a is an array, the compiler first converts the array into a pointer to its first element. This is a rule in the C standard. So a[1] is actually (&a[0])[1]. Then the definition above applies: (&a[0])[1] is *(&a[0] + 1), so it means “Take the address of a[0], add one element, and access the object the result points to.”
Thus, a[1] in the calling code and array[1] in the called code have the same result, even though one starts with an array and the other uses a pointer. Both use the address of the first element of the array, add one element, and access the object at the resulting address.
C defines operations of addition and subtraction of integers and pointers, collectively called pointer arithmetics. The language specification says that adding N to a pointer is equivalent to advancing the pointer by N units of memory equal to the size of an object pointed to by the pointer. For example, adding ten to an int pointer is the same as advancing it by ten sizes of int; adding ten to a double pointer is equivalent to advancing the pointer by ten sizes of double, and so on.
Next, the language defines array subscript operations in terms of pointer arithmetics: when you write array[index], the language treats it as an equivalent of *((&array[0])+index).
At this point, the language has everything necessary to pass arrays as pointers: take &array[0], pass it to the function, and let the function use array subscript operator on the pointer. The effect is the same as if the array itself has been passed, except the size of the array is no longer available. The structure of your API indirectly acknowledges that by passing the size of the array as a separate parameter.
You have an array of int, identified by the address of its first element.
array[1] Is equivalent to *(array + 1) which mean "The value of what is pointed by array + the size of one element, which is known as int because you prototyped it as int *"
When you declare a to be an array of size 10, the c program stores the address of a[0] in a and since the memory is allocated continuously therefore you can access the subsequent integers by using a[2], a[4] etc. Now when you copy a to array it is actually the address that gets copied and therefore you can access the integers using array[0], array[1] etc.
I have a pointer to an array and i am unable to access the members of the array.To make it more precise,plz see the code below:
int struc[2] = {6,7};
int (*Myval)[2];
Myval =&struc;
Now the Myval is pointing to the start of the array and upon dereferencing the pointer we would get the 1st element of the array i.e
printf("The content of the 1st element is %d\n",(*Myval[0]));
gives me the first elemnt which is 6.
How would i access the 2nd elemnt of the array using the same pointer.
If i would do Myval++,it would increment by 8 since the size of the array is 8.
any suggestions or idea??
Thanks and regards
Maddy
I think that while int (*)[2] is a valid type for pointing to an array of two ints, it is probably overkill for what you need, which is a pointer type for accessing the members of an array. In this case a simple int * pointing to an integer in the array is all that you need.
int *p = struc; // array decays to pointer to first element in assignment
p[0]; // accesses first member of the array
p[1]; // accesses second member of the array
As others have indicated, if you do use a pointer to an array, you have to dereference the pointer before using a subscript operation on the resulting array.
int (*Myval)[2] = &struc;
(*Myval)[0]; // accesses first member of the array
(*Myval)[1]; // accesses second member of the array
The C declaration syntax of 'declaration mirrors use' helps here.
You would not dereference, but subscript, like with other pointers
Myval[0][1] // accesses second element
The first [0] is probably a little confusing, since it suggests that you are handling with an array. To make clear that you are working with a pointer, i would use dereferencing
(*Myval)[1] // accesses second element
The (*Myval) dereferences the array pointer and yields the array, and the following subscript operation addresses and dereferences the item you want.
This should work as well:
*( Myval[0] + 1 )