i have a program about 2-D arrays
base adress is 8678
#include<stdio.h>
#include<conio.h>
main()
{
int arr[3][3]={
{83,8,43},
{73,45,6},
{34,67,9}
};
printf("%d ",&arr+1); //points to 8696
printf("%d ",arr+1); //points to 8684
return 0;
}
what is the difference between arr+1 and &arr+1?
Well, they're different things. arr decays in most contexts to a pointer to the first element of your array - that means a pointer to the first 3-element row in your 2D array: type int (*)[3]. arr + 1, then, points to the second row in the array.
&arr is the address of the array itself (type int (*)[3][3]), so &arr + 1 points to memory just past the end of the entirety of your 2D array.
You can confirm this behaviour easily by printing differently. Specifically, printing the offsets to the new pointers rather than the values themselves will help clear things up. The output from your program from these print statements:
printf("%ld\n",(intptr_t)(&arr+1) - (intptr_t)arr);
printf("%ld\n",(intptr_t)(arr+1) - (intptr_t)arr);
Will be the decimal offsets to &arr+1 and arr+1 respectively. Here's the output from a test run I just made:
36
12
36 matches up: 3 rows × 3 columns × 4 bytes per entry = 36 bytes. So does the 12: 1 row × 3 columns × 4 bytes per entry = 12 bytes.
Note - you're also printing pointers using %d, which is wrong. You should probably be using %p for that.
You can figure this out with the help of this equivalence: X[Y] === *(X+Y)
Since *(arr+1) === arr[1], arr+1 === &arr[1]
Similarly, &arr+1 === &((&arr)[1])
What is (&arr)[1]? Well, (&arr)[0] === *&arr === arr,
that is, the 3x3 array itself, so (&arr)[1] is the 3x3 array following that,
and &arr+1 === &((&arr)[1]) is the address of the 3x3 array following &arr ... a pointer to the byte just past the entire array.
Arr+1 gives the next element in an array while &arr +1 gives the address of next array of integers
array + 1 means the array[1] 's address and it costs 3 int memory.
&array + 1 means the address of array[0] add 1;
Related
Hello I am learning c in school and having a little confusion on this problem.
That is,
b is two d array, and I am trying to implement around printing values and the adress,
but why is *(b+1) giving the same thing as b+1?
I thought *(b+1) would give the value of the first element of the second row.
and if I change printf("%p\n", *(b+1)) to printf("%d\n", *(b+1)), it just gives a garbage value.
Why is it working like this?
I appriciate any feedback! thank you
int main()
{
int b[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
printf("b:\n");
print_2d_array(3, 4, b);
printf("\n");
printf("%p\n", b);
printf("%p\n", *(b+1));
printf("%p\n", b+1);
return 0;
}
Output is like this,
b:
0 1 2 3
4 5 6 7
8 9 10 11
0x7ffeecee6730
0x7ffeecee6740
0x7ffeecee6740
The question you have asked essentially boils down to a question about the nature of an array and the address of an array, which is a fairly well covered topic (see this for example). However, you likely confused yourself with the pointer arithmetic, so this answer tries to clarify some of that.
In C, when array object is used in an expression, its value and type becomes the same as the pointer to its first element.
In your case, you have:
int b[3][4] = { /* ... */ };
/* ... */
printf("%p\n", *(b+1));
printf("%p\n", b+1);
If we consider the last print statement,b in the expression b + 1 becomes the same as &b[0] + 1, and this would be the same as &b[1].
When we consider the print statement before the last one, we note that *(b+1) is defined to be the value b[1]. However, the result of that expression is an array of 4 int. That array now takes on the value and type of its first element, which would be &b[1][0].
Since you need to be able to find the address of the first element of an array from the array itself, the address of an array, &b[1], has the same pointer value as the address of its first element &b[1][0].
However, &b[1] and &b[1][0] have different types. The former is a pointer to an array, while the later is a pointer to an int.
For additional information, I encourage you to read the linked question at the top of this answer for more about arrays and the address of arrays.
*why is (b+1) giving the same thing as b+1?
The output address is numerically same but their type is different.
The type of *(b+1) is int [4] whereas the type of b+1 is int (*)[4].
*(b+1), when used in an expression, will convert to address of first element of second row1):
*(b + 1) -> b[1] -> ((b[1]) + (0)) -> &(*((b[1]) + (0))) -> &b[1][0]
and b+1 will give address of second row.
Address of an array and address of first element of that array are numerically same but their type are different.
*I thought (b+1) would give the value of the first element of the second row.
*(b+1) will give the second element of 2D array b which is nothing but a 1D array of 4 integers.
To access the first element of second row using *(b+1), you can do:
(*(b+1))[0]
To access the second element of second row using *(b+1), you can do:
(*(b+1))[1]
third element ....
(*(b+1))[2]
and so on .....
Note that *(b+1) is equivalent to b[1]1). So,
(*(b+1))[0] is equivalent to b[1][0]
(*(b+1))[1] is equivalent to b[1][1] .. and so on
Hope this clarifies your doubt.
1 ) From C Standards#6.5.2.1
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))..
I'm having a little bit of trouble understanding how this code outputs 10. I understand that p is the address of the first element in the pointer array, meaning p+1 is the address of the second element of the list. Meaning *(p+1) is the address of the first element of array n. Consequently * (*(p+1) + 1) evaluated to the 2nd element of array n. However, I'm getting confused as to how the below code prints the value 10, meaning the first element of array r. Help is greatly appreciated.
int m[4]={-2,3,6,8,9}, n[4]={7,6,4,3}, r[4]={10,-3,5};
int *p[3]={m,n,r};
printf("%d", *((p+1)[1]));
Starting at p:
p: {m, n, r}
p+1: {n, r}
(p+1): {n, r}
(p+1)[1]: r
((p+1)[1]): r
((p+1)[1]): {10, -3, 5}
*((p+1)[1]): 10
Note that (p+1)[1] means *((p+1)+1), not (*(p+1))+1.
You have an array of pointers, so p is the pointer to -2 (beginning of the m array) and p+1 is the pointer to 7 (beginning of the n array).
So p is the pointer to the beginning of the array that contains 3 pointers and p+1 is the pointer to the beginning of an array that contains 2 pointers and when you write (p+1)[1] you get the same result as p[2].
*p[2] == *(p+1)[1] == *(p+2)
I was given this function and I need to explain what it does without other context.
What my interpretation is: The address of the first element of an array is inputted into arrFunc with some length L1, and an integer pointer p is declared and initialized to point to the first element of arr1.
The while loop is what confuses me. My interpretation is (and I'm a beginner when it comes to programming) is that if the contents of p (which I believe contains the address of the first element of arr1) is less than the address of the last element of arr1, then increment the value inside the first element by 5, then increment p to go on to the next element of the array. The biggest thing that confuses me about the while loop is the comparison of two addresses (p<arr1+L1).
I guess my other question is, is the condition in the while loop comparing the two addresses, or is it comparing the values stored in those addresses?
void arrFunc(int *arr1, int L1)
{
int *p = arr1;
while(p< arr1 + L1)
{
*p+=5;
p++;
}
}
The function adds 5 to the elements of the provided array, but only to the first L1 elements (might not be the whole array).
To answer the second question, about adding an int to a pointer, in terms of memory C will manage to add the right amount based on an element size ; meaning it doesn't simply add the int to the address, it adds
sizeof(*array) * intValue
It actually adds the size of an array element multiplied by that integer value. Here it adds sizeof(int) * L1 to get
arr1 + L1
to be compared with p. (p++, similarly, is incremented, in terms of addresses, by sizeof(int)).
This function takes an array of size L1 and add 5 to each of the element. So if an array of size 4 like following is inputted
10 20 30 40
After executing this function the output will be
15 25 35 45
i want to print the value which contain in the multidimensional array.I know that if we write something like arr[3][4] then arr[0] is the pointer to the first element in the that multidimensional array.
I want to ask why this code give me garbage value after the program print the number containing in the multidimensional array?
this is the code:
#include <stdio.h>
#define ROW 3
#define COLL 4
int main(void) {
int arr[ROW][COLL]={{1,2,3,4},
{5,6,7,8},
{9,10,11,12}};
int *ptr;
for(ptr=arr[0];ptr<arr[ROW]+COLL;ptr++){
printf("%d ",*ptr);
}
printf("\n");
return 0;
}
this is the result when i compile the above code:
1 2 3 4 5 6 7 8 9 10 11 12 -1079481492 134513936 0 -1079481352
but after changing the for loop to the following:
for(ptr=arr[0];ptr<=arr[ROW-1]+COLL-1;ptr++)
the code work and give the exact number which contain in the multidimensional array.
Because arr[ROW] is an out-of-bounds access. The last valid position in arr is arr[ROW-1]. Thus the first version of your code invokes undefined behaviour.
The pointer to the last element is
arr[ROW-1] + COLL - 1
So you loop should be
for (ptr = arr; ptr < arr[ROW-1] + COLL; ptr++) {
Elements of an array are indexed from 0 so the last element in your matrix is arr[ROW-1][COLL-1].
When your pointer reaches arr[2] + COLL there is no such element because the second coordinate of the last element in last row is [COLL-1].
Elements of an array are stored in 1D so arr[0] + 4 is acctualy arr[1][0].
When you increment ptr++ it tells the compiler to access the next memory location after the current. So, when ptr points to a[0] + 4 it works because the compiler access the fifth value after a[0][0] which is actually the first value in the next row, arr[1][0], because their memory locations are next to each other.
When your ptr points to arr[4] + i, i = 0, 1, 2, 3 you get bad output because those elements are not in your array.
Because your first element, 1, is at arr[0]+0,
5 is at arr[1]+0,
9 is at arr[2]+0,
10 is at arr[2]+1,
11 is at arr[2]+2,
and 12, which is the last element of your array is at arr[2]+3.
but your for loop keeps moving even after the array ends, that is, until the memory location arr[3]+4 is reached. Giving you four garbage values because we have stored nothing in the memory after arr[2]+3.
so the for loop should be like:
for (ptr=arr; ptr <= arr[ROW-1]+COLL-1; ptr++);
which is equivalent to:
for (ptr=arr[0]; ptr <= arr[ROW-1]+COLL-1; ptr++);
as arr[0] and arr point to the same location in memory.
NOTE- try reading how memory is allocated in arrays of multiple dimensions.
I have this question:
say starting address is 100.
int arr[2][3][2] = {{{2,4},{7,8},{3,4}},{{2,2},{2,3},{3,4}}};
printf(“%u %u %u %d \n”,arr,*arr,**arr,***arr); // Line 2
printf(“%u %u %u %d \n”,arr+1,*arr+1,**arr+1,***arr+1); // Line 3
}
Answer:
100, 100, 100, 2
114, 104, 102, 3
Explanation:
For Line 3: arr+1 increases in the third dimension thus points to value
at 114, *a+1 increments in second dimension thus points to 104, **arr +1
increments the first dimension thus points to 102 and ***arr+1 first gets the
value at first location and then increments it by 1. Hence is the output of second line.
My Question - I tried my best. but i could get what explanation meant for Line 3 ! please explain
What is type of int arr[2][3][2]? It is array of 2 elements of type int [3][2]. This is 3rd dimension.
What is int [3][2]? It is array of 3 elements of type int [2]. This is 2nd dimension.
What is int [2]? It is array of 2 elements of type int. This is 1st dimension.
Here's diagram
In line 2:
arr points to first element of 3rd dimension,
*arr points to first element of 2nd dimension,
**arr points to first element of 1st dimension,
***arr takes the value of first element of 1st dimension.
You can see from diagram that all dimensions start from address 100. Hence the output of line 2: "100, 100, 100, 2".
In line 3:
arr + 1 points to second element of 3rd dimension,
*arr + 1 points to second element of 2nd dimension,
**arr + 1 points to second element of 1st dimension,
***arr + 1 takes the value of first element of 1st dimension and increments it.
You can see from diagram that second element of 3rd dimension has address 112 (not 114!), second element of 2nd dimension has address 104, second element of 1st dimension has address 102. Hence the output of line 3 must be: "112, 104, 102, 3"
Your answer is wrong. The first value for line 3 should be 112, not 114.
When you use arithmetic on a pointer, it changes the address by some number of elements (of whatever size the array stores). When you use an array as if it were a pointer, C will manage that for you.
When you use arr, the compiler will say you have a pointer to an array holding two elements of type int[3][2]. So adding one to that means adding sizeof(int[3][2]) which is 12. Here is a table to show this:
code element type ints per element bytes per element array length
-----------------------------------------------------------------------------
arr int[3][2] 6 12 2
*arr int[2] 2 4 3
**arr int 1 2 2
there isn't much value in any "explanation" within your example. See, you're mixing things up. That's because your multi--ing (**arr and the like) only is sensible, if you're allocating with C's malloc. Then the rows of a 2D array are arr[i] of type (int *), and within any row a column value is arr[i][j] of type (int), and the whole 2D matrix is *arr of type (int *). In 3D you have arr[i][j][k] of type (int) down to **arr for the whole 3D structure. But using int arr[2][3][2] = {...}, just use arr[i][j][k] to get a matrix element and i.e. arr[0], arr[1] for the rows. Pointers aren't really useful with those compile-time allocated 2-3D matrices. Always remember **arr is a pointer to a pointer to a pointer, if and only if someone came along and did all the C-malloc-ing. Regards, M.