pointer indirection confusion - c

I have an array as:
int x[3][5]={
{1,2,3,4,5},
{6,7,8,9,10},
{11,12,13,14,15}
};
What does *x refer to?
*(*x+2)+5 refer to "8".How does that happen?
Is *(*x+2) same as *(*x)+2?
What if I do:
*n=&x;
Where is the pointer n pointing to? if it would have been only x and not an & then it would have been the base address.What for now?

*x is a dereference operation. In other words, "give me what x is pointing at". Since this is an array (of arrays), dereferencing x will give you the first array. This is equivalent to the array access syntax of x[0].
*(*x+2)+5 is equivalent to x[0][2] + 5, which gives you 8. This is because:
*x is the same as x[0] (see #1) and *(x + 2) is the same as x[2]. Once you've done two dereferences, you've gone from an array of arrays (similar to a double-pointer) to an array (single pointer) to an actual number (the third item in the first array). Then, it's just 3 + 5 = 8.
*(*x+2) is equivalent to x[0][2] (see #2), which is 3 (third element in array). However, *(*x) + 2 gives you x[0][0] + 2 (first element in array plus 2), which is 1 + 2 = 3. Same answer, but very different way of getting it.

*x refers to the first array ({1,2,3,4,5}), and is equivalent to x[0]. Adding one to x move to the next array, so *(x+1) would refer to the second array, and would be equivalent to x[1].
*(*x + 2) is therefore the third element in the first array, which is 3. This means that *(*x + 2) + 5 is equal to 8.
The parentheses matter a lot, for example *(*(x+2)) would be the first element in the third array.
*(*x + 2) results in the same value as *(*x) + 2, but does not use the same element of the array.

x is a int** so it's like if you have a first layer of pointers and everyone of them point to a int* (so an array of int).
When you write *x you obtain the address that contains the address which points to the first row of your multi dimensional array.
So if you take (*x + 2) if it's like referencing to first row of you array and then add 2 to the address: you obtain the address of the third element of first row. But since this is still a pointer you add an external *(*x+2) to exactly obtain third element of first row.

Think of it this way:
typedef int Int5[5];
Int5 x[3];
x is an array with 3 elements. Each of those three elements is a array of 5 ints.
What does *x refer to?
x is the same as '&x[0]so*xis the same asx[0]` which is the first 5-element array.
*(*x+2)+5 refer to "8". How does that happen?
*x is x[0], and x+2 is &x[2] so *x+2 is &x[0][2] and *(*x + 2) is x[0][2] which happens to be 3. Add five to that for 8.
Is *(*x+2) same as *(*x)+2?
*(*x+2) is x[0][2] as we've seen. *(*x) would be x[0][0], so *(*x)+2 is x[0][0]+2. So both *(*x+2) and *(*x)+2 end up equaling 3, but that is merely a coincidence.

All the answers are 100% correct and I will just generally explain this part *n=&x in general terms
&x generates a pointer (variable containing an address of another variable) and stores it in n and to get the value pointed to by n, you *n called de referencing or indirection.
To really understand this pointer business, you need to study how computers store values in memory.

Related

What the following code prints / with arrays, pointers etc

I have problem solving this problem, so if anyne had a similar problem it would help me a lot.
short y[2][3]={{0123},{0x12345}},*p=y[1];
printf("01:%x\n", y);
printf("02:%x\n", p);
printf("03:%x\n", sizeof(y));
printf("04:%x\n", sizeof(y[0]));
printf("05:%x\n", sizeof(&y[0]));
printf("06:%x\n", sizeof(*p));
printf("07:%x\n", sizeof(p++));
printf("08:%x\n", *p++);
printf("09:%x\n", *p);
return 0;
Can anyone explain to me why the printout is like this?
01:61ff10
02:61ff16
03:c
04:6
05:4
06:2
07:4
08:2345
09:0
My opinion:
01:Prints the address where the array y begins.
02:Prints the address of the pointer, which points to the second element of the array. Since we have 2 * 3 elements that are of type short, each subsequent element of the zero element will increase by 6.
03:Since we have 2 * 3 elements, which is equal to 6, but the elements of the type are short, so it will print hexadecimal c
04:the number of elements in the zero position is 3, but they are of the short type, so it prints 6
05:prints the sizeof addresses of the first element of the array which is 4
06:I don't know why it prints 2 here
07:Prints the sizeof of the pointer address which is 4, it will increase after printing
08:I do not understand
09:I do not understand
Can anyone explain why it prints like this?
OK, let's see:
#01: The address of y.
#02: The value of p, which holds the address of y[1], which is the second element of type short[3]. The size of a short is apparently 2 on your system, so the offset to #01 is 6.
#03: The size of the array y, 2 * 3 * sizeof (short) give 12, in hex c.
#04: The size of the element y[0], which is of type short[3]. 6, as you found.
#05: The size of the address of y[0], and apparently the size of an address is 4 on your system.
#06: The size of the object that p points to. This is a short, so 2.
#07: The size of the expression p++, which is an address, so 4. And no, p is not incremented, since the expression is not evaluated.
#08: The value of the object that p points to, which is y[1][0]. Since the initializing value of 0x12345 is an int too big to be stored in a short, it is truncated to 0x2345. After reading the value, p is incremented.
#09: The element p points to, which is y[1][1]. It was initialized to 0.
Notes:
You should have got warnings from your compiler:
The mentioned initializer is truncated.
The format for pointers/addresses is %p.
The type of the result of sizeof might not match the format %x.
You should take warnings seriously, they are always a hint that you most probably made an error.
N6) Sizeof(*p) is size of datatype pointed by p. p is pointer to short: so 2 bytes.
N8) p is pointer to short, it`s pointing to array element y[1][0].
y[1] and y[1][0] have the same memory address.
All array elements are short, 0x12345 truncates to 0x2345 upon array initialisation. So output is 2345.
Also, p++ increases pointer value to point to next short y[1][1].
N9) Because of p++ in step N8, pointer now points to y[1][1], which was initialised to 0 (by default, because init value not provided) - output is 0.

Get difference of two address of array(use & operator)

I want to get the address difference between two elements in an array.
int vector[] = { 28, 41, 7 };
printf("%d\n", &vector[2]); // 1703652
printf("%d\n", &vector[1]); // 1703648
printf("%d\n", &vector); // 1703644
printf("%d\n", &vector[1] - &vector); // 1
The result I expect(Last Line) is 4 because the data type was int.
Further, each result of address has 4 differences.
But why is the result of
&vector[1] - &vector
1 and not 4?
And how do I get 4 by using subtraction operator?
pointer arithmetics in C language works on the type of the object. It does not matter how big the object is. The reference to the next object minus reference to the previous is always one object
So if we add 5 to the pointer it will point 5 objects ahead. If we increment the pointer it will reference the next object. It helps indexing and iterating across the objects.
When you printf the address (your format is wrong - you should use %p instead) it is printed in bytes. So the difference between the consecutive objects will be equal the size of the object (plus the optional padding).
And How to I get 4 by using subtraction operator???
Cast the pointers to the type which sizeof is one for example char.
(char *)&vector[1] - (char *)&vector
You can calculate the difference of pointers to byte-sized values by casting the pointers to char *:
printf("%d\n", (char*)&vector[1] - (char*)vector);

Subtracting addresses in a 3d array

I created a 3d array
a[2][3][2]
Now when I try to print
printf("%d",a[1] - a[0]);
I get 3 as the output.
What I understand is that a[1] gives me the address of a[1][0][0] element and a[0] the address of a[0][0][0].
Let Address of a[0][0][0] is BA then Address of a[1][0][0] is BA + 4*2*3 where 4 byte is the memory space of an integer datatype
I was expecting the result to be 6.
Similarly I tried
printf("%d",(&a + 1) - &a);
and the output received was 1.
Where am I going wrong?
Edit 1: Entire Code
#include<stdio.h>
int main(){
int a[2][3][2] = {{{1,2},{3,4},{5,6}},{{7,8},{9,10},{11,12}}};
printf("%d",a[1]-a[0]);
return 0;
}
What I understand is that a[1] gives me the address of a[1][0][0] element and a[0] the address of a[0][0][0].
This is wrong a[0] will give the address of the first 2D array. The address of the first 2D array and the address of a[0][0][0] might be co-incident, but they are not the same.
Specifically &a +1 is not equal to &a[0][0][0] +1
Let's break the expression a[1] - a[0] apart:
a[1] - refers to the second [3][2] array.
a[0] - refers to the first [3][2] array.
Now, when arrays are used in most contexts, they decay into pointers to the first element. So a[i] will decay into a pointer to a 2d array int(*)[2].
The difference is calculated in sizeof(int[2]) as dictated by pointer arithmetic. And you can see that there are 3 units of int[2] in the range [a[0], a[1]).

Multidimensional array and addressing

I have an issue with the multidimensional arrays. Maybe the solution is much easier.
int arr[2][2]; //multidimensional array
My simple question is: why the
arr[0][2] and arr[1][0]
or
arr[1][2] and arr[2][0]
are on the same address in my case?
I checked this problem in Linux and Windows environment. And the issue is the same. I have checked tutorials and other sources, but no answer.
The pointer &arr[0][2] is the one-past-the-end pointer of the array arr[0]. This is the same address as that of the first element of the next array, arr[1], which is &arr[1][0], because arrays are laid out contiguously in memory.
arr[2][0] is a bit tricker: arr[2] is not a valid access, but &arr[2] is the one-past-the-end pointer of the array arr. But since that pointer cannot be dereferenced, it doesn't make sense to talk about arr[2][0]. arr doesn't have a third element.
C stores multi-dimensional arrays in what is called row-major order. In that configuration, all the data for a single row is stored in consecutive memory:
arr[2][2] -> r0c0, r0c1, r1c0, r1c2
The alternative would be column-major order, which places the columns consecutively.
Since you have specified the length of the row (number of cols) as 2, it follows that accessing column 2 (the third column) will compute an address that "wraps around" to the next row.
The math looks like:
&(arr[row][col])
= arr # base address
+ row * ncols * sizeof(element)
+ col * sizeof(element)
= arr + sizeof(element) * (row * ncols + col)
In your case, arr[0][2] is arr + (0*2 + 2) * sizeof(int), while arr[1][0] is arr + (1*2 + 0)*sizeof(int).
You can do similar math for the other variations.
Array indexing is identical to pointer arithmetic (actually, the array name first is converted ("decays") to a pointer to the first element before the []-operator is applied):
arr[r][c] <=> *(arr + r * INNER_LENGTH + c)
Your array has two entries per dimension. In C indexes start from 0, so for each dimension valid indexes are 0 and 1 (i.e. total_entries - 1). Which makes three of your expressions suspective in the first place:
arr[0][2] // [outer dimension/index][inner dimension/index]
arr[1][2]
arr[2][0]
We have these cases:
Both indexes are valid: no problem.
Only the address is taken, the element is not accessed and
the outer index is valid and the inner (see below) index equals the length of the inner dimension: comparison and certain address arithmetic is allowed (other constraints apply!).
the outer index equals the length of the outer dimension, and the inner index is 0: The same.
Anything else: the address is invalid and any usage (take address, dereference, etc.) invokes undefined behaviour.
What exactly goes on in memory might become a bit more clear if we use different lengths for the dimensions and have a look how the data is stored:
int arr[3][2];
This is an "array of 3 arrays of 2 int elements". The leftmost dimension is called the "outer", the rightmost the "inner" dimension, because of the memory layout:
arr[0][0] // row 0, column 0
arr[0][1] // row 0, column 1
arr[1][0] // ...
arr[1][1]
arr[2][0]
arr[2][1]
Using the formula above, &arr[0][2] (arr + 0 * 2 + 2) will yield the same as &arr[1][0] (arr + 1 * 2 + 0), etc. Note, however, while the addresses are identical, the first version must not be dereferenced and the compiler may generate incorrect code, etc.
Array indexing in C is similar to adding the value of the index to the address of the first element.
In the multidimensional array that you describe, you have 2 elements on each dimension: 0 and 1. When you introduce a number larger than that, you're referencing an element outside that dimension. Technically, this is an array out of bounds error.
The addresses break down like this:
arr[0][0] - &arr[0] + 0
arr[0][1] - &arr[0] + 1
arr[1][0] - &arr[0] + 2
arr[1][0] - &arr[0] + 3
When you write arr[0][2], you're referencing address &arr[0] + 2, which is the same as arr[1][0]. It all just pointer math, so you can work it out pretty easily once you know how it works.
You can look in your two dimensional array as a long one dimensional array:
[00][01][10][11]
With the pointers arithmetic, another representation of this long one dimensional array is:
[00][01][02][03]
So looking in cell [10] is exactly the same as looking into a cell [20] in pointer arithmetic point of view.

different representation of array element [duplicate]

This question already has answers here:
With arrays, why is it the case that a[5] == 5[a]?
(20 answers)
Closed 9 years ago.
consider following C code
int a[]={1,2,3,4};
printf("%d",2[a]);
this prints "3".How is it possible? I know in a[2] a is the base address of array.But in 2[a]
what is 2? and how it accessses array a?I am totally confused with this representation of array.
There are two things to remember here:
The first is that array access is basically just a fancy way of using pointer arithmetic. For example, if you have the array
int a[10];
then
a[3] = 5;
is equal to
*(a + 3) = 5;
The second thing to remember is that addition (like in a + 3 above) is commutative, so a + 3 is the same as 3 + a. This leads to e.g.
*(3 + a) = 5;
which can be interpreted as
3[a] = 5;
int a[]={1,2,3,4}; is an integer array containing 4 elements and a is the Base Address, Let the Base Address be denoted by X . Now a[1] means element at address X + sizeOf(int) * 2 = Y (suppose) i.e. element at address Y, likewise 2[a] means element at adsress sizeOf(int) * 2 * X = Y.
Thus even if you write a[2] or 2[a] eventually complier recognizes it as Y and refres to the element at address Y which is 3 in our case.
Hope it addresses the problem right.
*(expr1+expr2) is equivalent to expr1[expr2] or expr2[expr1].
*(expr2+expr1) is equivalent to expr2[expr1] or expr1[expr2].
It is just another way to write an element of an array.
In int a[]={1,2,3,4};, element at index 3 can be referenced by many methods:
As an array element: a[3]
Using pointer: *(a + 3) or *(3 + a) [Addition is commutative in arithmetics and in C]
Now you can write the second way of representation using pointer as 3[a], i.e. a[3] is equal to *(a + 3) is equal to *(3 + a) is equal to 3[a].

Resources