different representation of array element [duplicate] - c

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].

Related

Achieve the output in one statement

I was given this question by my school teacher. I was supposed to add in one statement in the C code and achieve this desired output.
I have tried but i am stuck. I think the main idea of this question is to establish the relationship between the int x[] and the y[] string as i increases from 0 to 6.
The code is below:
#include <stdio.h>
int main(){
int i, x[] = {-5,10,-10,-2,23,-20};
char y[20] = "goodbye";
char * p = y;
for (i=0;i<6;i++){
*(p + i) = //Fill in the one line statement here
}
y[6] = '\0';
printf("%s\n",p); //should print out "byebye"
}
As you can see the ascii value of the characters b is from 5 lesser than g and similarly for y it is 10 greater than o..so it will be (This meets the criteria of using x) (solution utilizing the values of x)
*(p+i) = (char)(*(p+i)+x[i]);
Yes one thing that is mentioned by rici is very important. *(p+i) is nothing other than p[i] - in fact it is much leaner to use and underneath it is still being calculated as *(p+i).
From standard 6.5.2.1p2 C11 N1570
A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).
The standard mentions this also. Being said this it would be as simple as
p[i]+=x[i];
Thoughts that came to my mind while solving.
It would be (things that came to my mind when I saw it very first time - this is establishing no relation between x and y).
*(p + i) = "byebye"[i];
String literals are basically arrays and it decays into pointer to the first element of it and then we do this *(decayed pointer + i). This will eventually assign the characters of "byebye" to the char array y.
Or something like this:- (too many hardcoded values - this does relate x and y)
*(p+i) = *(y+4+i%3);
Using a the modulus operation you can manipulate your loop to assign byebye to the 6 *char values in p.
This works because you are starting from y[4] which is 'b'.
The 6 in the for loop is your next hint. You need to iterate through bye twice. bye has 3 characters.
This gives you:
*(p + i) = y[4+(i%3)];

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.

What does 1[index] mean in c? [duplicate]

This question already has answers here:
With arrays, why is it the case that a[5] == 5[a]?
(20 answers)
Closed 7 years ago.
Why does the below code not generate an error and print the value stored in arr then followed by a junk value ?
int main() {
int arr[1]={10};
printf("%d %d\n",0[arr], 1[arr] );
return 0;
}
In C, 0[arr] == arr[0].
So,
0[arr]==arr[0]==10.
and
1[arr]==arr[1]==Junk value
Check this SO question and it's answers.
The C standard defines the [] operator as follows:
a[b] == *(a + b)
Therefore a[5] will evaluate to:
*(a + 5) and 5[a] will evaluate to:
*(5 + a) and from elementary school math we know those are equal. (Addition is commutative.)
This is the direct artifact of arrays behaving as pointers, "a" is a
memory address. "a[5]" is the value that's 5 elements further from
"a". The address of this element is "a + 5". This is equal to offset
"a" from "5" elements at the beginning of the address space (5 + a).
1[arr] is the same as arr[1].
This is possible because E1[E2] is equivalent to (*((E1) + (E2)) in C by definition of [] operator.
Note that if you declare:
int arr[1]={10};
There is only element in the array, arr[0] and there is no arr[1] element.

How to make an O(N) algorithm solution? [duplicate]

This question already has answers here:
Equilibrium index of an array of large numbers, how to prevent overflow?
(2 answers)
Closed 7 years ago.
This problem is a practice problem found on Codility, a link can be found here to an example. https://codility.com/public-report-detail/
Problem: We have an array of N integers -- where 0 <= N < 100,000 -- where each integer is between -2,8XX,XXX and +2,8XX,XXX (signed int range). The challenge is to find whether there exists a point, P, where the summation of all array values prior to P are equal to the summation of those after P.
i.e. sum(A[0] to A[P-1]) == sum(A[P+1] to A[N-1])
ex.
A[0] = -1
A[1] = 3
A[2] = -4
A[3] = 5
A[4] = 1
A[5] = -6
A[6] = 2
A[7] = 1
P = 1 is an equilibrium index of this array, because:
A[0] = −1 = A[2] + A[3] + A[4] + A[5] + A[6] + A[7]
P = 3 is an equilibrium index of this array, because:
A[0] + A[1] + A[2] = −2 = A[4] + A[5] + A[6] + A[7]
P = 7 is also an equilibrium index, because:
A[0] + A[1] + A[2] + A[3] + A[4] + A[5] + A[6] = 0
The program can quit after the first instance of an acceptable P is found.
There was 30 minutes to complete the challenge, and evidently the expected solution is O(N). I can think of a few O(NlogN) solutions to the problem -- and an O(N) solution involving the summation of the array before removing values one at a time, but this wouldn't work for extreme cases in which every value is of 2,8XX,XXX,XXX.
I'm working in C++ but even pseudo would be great. Suggestions on the proper algorithm to handle this constraint?
A version that works if you can use 64-bit integers: Calculate the cumulative sum of the array, then copy the array and calculate the cumulative sum again from the back. Then step through both cumulative sums and where the value at a given index is equal in both, you have P.
E.g., your example array becomes
-1 2 -2 3 4 -2 0 1
and
1 2 -1 3 -2 -3 3 1
* * *
where the P points have been marked with an asterisk.
If you can't use 64-bit integers outright, then I guess I would make additional arrays for remainders, i.e. manually recreate 64-bit functionality with another signed int array, and require both arrays to match when checking. I don't think there's anything else you could do under this general approach.

pointer indirection confusion

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.

Resources