C array indexing - c

I have a pretty simple question but it confuses me a bit
For example:
int a[] = {0,1,2,3,4,5,6,7,8,9};
I have a question asking what the value of: a + 3 is
Simple question,what I tried was just adding 3 spots so the array would start from 2 and onwards.

Value of a + 3 is a pointer value of type int * that points to memory location of a[3] - an array element that contains value 3 in your example. That is a direct answer to the question you asked. Is that what you wanted to hear?
P.S. It is not clear what you mean by "array would start from 2 and onwards". Where did that "2" come from?

If you just referenced a, it is a pointer to the first element of the array, so a[0] - that is, a pointer of type int *. Adding to the array is in most cases equivalent to adding to such a pointer, so a+3 will refer to a[3] or the value 3 in your case.

if you want the value of "a" then the value will be its address as array acts as a pointer and points to the first element of the array i.e. a[0]
so lets suppose the address of a is 0059FE8C then the address of a+3 will be 0059FE98.
As each integer is of 4 bytes so add 4 each for each 0059FE8C +4+4+4= 0059FE98.
Now if you will do *(a+3) for int a[] = {0,1,2,3,4,5,6,7,8,9} then this means a[3] which has value 3.

If the starting address of your array a is 1000 then a+3 would give you 1000 + 3*4, ie, 1012 (assuming int is of 4 bytes). It is because array names are decayed to pointers to its first element.
Dereferencing a + 3, which is a pointer to fourth element of the array, would give 3 (fourth element of the array).

Related

Printf and Array

I was asked this question as a class exercise:
int A[] = {1,3,5,7,9,0,2,4,6};
printf("%d\n", *(A+A[1]-*A));
I couldn't figure it out on paper, so went ahead to compiling a simple program and tested it and found that printf("%d",*A) always gives me 1 for the output.
But I still do not understand why this is the case, hence it would be great if someone can explain this.
A is treated like a pointer to the first element of array of integers.
A[1] is the value of the first element of that array, which is 3 (indexes are 0-based)
*A is the value to which A points, which if the zeroth element of array, so 1.
So
A[1] - *A == 3 - 1 == 2
Now we have
*(A + 2)
That's where pointer arithmetic kicks in. Since A is a pointer to integer, A+2 points to the second (0-based) item in that array and *(A+2) gets its value.
So answer is 5.
Also please note for future reference that pointer to an integer and array of integers are somewhat different things in C, but for the purposes of this discussion they are the same thing.
Break it down into its constituent parts:
A by itself is the memory address of the array, which is also equivalent to &A[0], the memory address of the first element of the array.
A[1] is the value stored in the second element of the array, which is 3.
*A dereferences the memory address of the array, which is equivilent to A[0], the value stored in the first element of the array, which is 1.
So, do some substitutions:
*(A+A[1]-*A)
= *(A+(A[1])-(A[0]))
= *(A+3-1)
= *(A+2)
The notation *(Array+index) is the same as the notation Array[index]. Under the hood, they both take the starting address of the array, increment it by the number of bytes of the array element type (in this case, int) multiplied by the index, and then dereference the resulting address. So *(A+2) is the same as A[2], which is 5.
Arrays used in expressions are automatically converted into pointers pointing at the first elements of the arrays except for some exceptions such as operands of sizeof or unary & operators.
E1[E2] is defined to be equivalent to *((E1) + (E2))
+ and - operator used to pointers will move the pointer forward and backward.
In this case, *A is equivalent to *(A + 0), which is equivalent to A[0] and it will give you the first element of the array.
The expression *(A+A[1]-*A) will
Get the pointer to the first element, which points at 1, via A
Move the pointer to A[1] (3) elements ahead via +A[1], so the pointer now points at 7
Move the pointer to *A (1) element before what is pointed via -*A, so the pointer now points at 5
Dereference the pointer via the unary * operator, so the expression is evaluated to 5
An array variable in C is only the pointer to the initial memory location for the array. So if you derreference the array, you will always get the value for the first position.
If you sum up 1 to the original array value, like *(A+1) you will get the second position.
You can get any position from the array using the same method:
*(A) is the first position
*(A+1) is the second position
*(A+2) is the third position
and so on...
If you declare the int array as int* A and allocate the memory and attribute the values, it is usually easier to visualize how this works.

How do pointers to arrays of integers work in C?

Take a look at this example:
#include <stdio.h>
#include <stdlib.h>
int main() {
int a[5] = {1,2,3,4,5}; // LINE A
int (*b)[5] = &a; // LINE B
printf("%d\n", (*b)[0]); // LINE C
}
I tried writing int (*b)[5] = a on LINE B but it didn't work. Can anyone explain why this didn't work? I though arrays decayed into pointers, so I can't quite understand why I needed to explicitly take address of a via &a. It's like a already is a pointer because it decayed, but now I take a address of a pointer? Double pointer? Huh?
Can anyone explain how (*b)[0] works? It's like I dereference b, which is itself a pointer to array of 5 ints, but I somehow take [0]'th element of it? Isn't the [0]-th element in this case 5 integers? I somehow end up with one integer though and it prints 1.
I'm really confused. Thanks.
int a[5]={1,2,3,4,5};
-------In Memory----------
| 1 || 2 || 3 || 4 || 5 |
---------------------------
101 105 109 113 117 //Assume these are addresses
By default Array Names act like pointers to there first element.
So a acts like pointer to first element(here element is integer)
so a is decayed into int *a;
thats why if you increment by one then it will jump to next addresses of element, as shown below
It will calculate like this: Address of 1st element + (n * sizeof(int))
(a+0)--->101 // 101 + 0*sizeof(int)
(a+1)--->105 // 101 + 1*sizeof(int)
(a+2)--->109 // 101 + 2*sizeof(int)
(a+3)--->113 // 101 + 3*sizeof(int)
(a+4)--->117 // 101 + 4*sizeof(int)
But &a acts like a pointer to complete array(in this case pointer to 5 ints), that means
when you add one to it,then it will try to point to next 5 integers.As shown below
(&a+1)----->121 //101 + 1*sizeof(a)
Thats why in this lineint (*b)[5] = &a; there is no problem,But when you try int(*b)[5]=a;
it gives error because a is pointer to single integer where as (*b)[5] is pointer to 5 integers.You cannot assign incompatible pointers types.
b is a pointer to array a. Dereferencing b will give the entire array a. So, when you will use *b in an expression, it represents the name for that dereferenced array. Since array names are converted to pointer to first element of array, *b decays to pointer to first element of a (or *b). *b has type int * after decay. Therefore (*b)[i] will give the ith element of the array that b points to.
When you declare - int a[5] - the compiler is using 'a' as a reference to the internal memory. 'a' itself is not a variable. Thus, &a does not work.

About C: pointer and Two-dimensional array

Here is the question:
What is the output of the program?
#include<stdio.h>
int main()
{
int A[2][10]={{1,2,3,4,5,6,7,8,9,10},{11,12,13,14,15,16,17,18,19,20} };
int (*v)[10]=A;
printf("**v=%d\n",**v);
printf("**(v+1)=%d\n",**(v+1));
printf("*(*v+1)=%d\n",*(*v+1));
printf("*(v[0]+1)=%d\n",*(v[0]+1));
printf("*(v[1])=%d\n",*(v[1]));
}
Outputs:
**v=1
**(v+1)=11
*(*v+1)=2
*(v[0]+1)=2
*(v[1])=11
Especially, I'm not very clear about how did *v divide array A into 10 parts, and please tell me the reasons about each output.
Thanks!
There's a concept called array decay at work. Also, pass each definition through cdecl.
The second line is
declare v as pointer to array 10 of int
Thus it is a pointer to an array of 10 elements. This pointer is initialized with A -- the array it points to is the first row of A.
Then, v+1 is another pointer to an array of 10 elements, following the first one. Thus, it is the second row of A.
In the **v, *v will be replaced by value of v[0], which is an address, say X, therefore the outer * will be used to indicate the value of address X, which is 1.
In the **(v+1), *(v+1) will become v[1], which is again an address, say Y, and the outer asterisk will give the value at address Y, which is 11.
*(*v+1)=2 => *(v[0] + 1) => here pointer shifts to the next location, and this location is v[0][1], which is similar to *(*(v+0)+1). Value at v[0][1] is 2.
*(v[0]+1)=2, same reason.
*(v[1])=11, v[1] holds the base address of the second row, which is the starting address of second row's 0th column, and the value at that location is 11.
Okay, let's review first, how arrays decay and second, how declarations work.
A is declared as a 2D array. When A is used in any expression, it will "decay" to a pointer to its first element. In C, a 2D array is made up of two 1D arrays. So an element of a 2D array is a 1D array. So when A is used in any expression, it will decay to a pointer to the first row of A, which is an array of 10 ints.
int (*v) [10] means that v is a pointer to an array of 10 ints. The assignment
int (*v)[10] = A;
is an expression, so A there has decayed to a pointer to 10 ints as well, so the assignment is valid.
So now when you look at **v, you are dereferencing first, v, which means you are getting what v points at, which is the first row of your 2D array. Then you are dereferencing *v, which means you are getting the first element of that first row. That is 1, so your output is 1.
When you look at **(v + 1), you are first adding 1 to the pointer v. Since v points to a row, adding 1 gets you a pointer to the next row. Then you do the double dereferencing as above and you get the first element of the next row, which is 11.
When you look at *(*v + 1), you are first dereferencing v, which means you get the first row. Then you add 1 to that, which gets you a pointer to the next element of the row. Then you dereference that, which gets you the 2, the second element.
To summarize: v points to the whole first row. *v points to the first element of the first row. (v + 1) points to the whole second row. (*v + 1) points to the second element of the first row.
After this, figuring out the rest is probably quite easy.

starting address of array a and &a

In the below two lines,
char a[5]={1,2,3,4,5};
char *ptr=(char *)(&a+1);
printf("%d",*(ptr-1));
This prints 5 on screen.Whereas when use a instead of &a,
char a[5]={1,2,3,4,5};
char *ptr=(char *)(a+1);
printf("%d",*(ptr-1));
This prints 1
Both a and &a are the starting address of the array.So Why is this difference?
Also
char *ptr=&a+1;
shows a warning.
Arrays aren't pointers! Read section 6 of the comp.lang.c FAQ for more information.
Let's look at your second case first, since it's the more "normal" and idiomatic looking. Line by line:
You declare an array a containing 5 char elements.
The name of the array (a) decays into a pointer to its first element in this context. You add 1 to that and assign the result to ptr. ptr points to the 2. No cast is necessary, though you have one.
You subtract 1 from ptr and then dereference and print - hence you get the 1.
Now, let's address the first case, again line by line:
You declare an array a containing 5 char elements.
You take the address of a, yielding a char (*)[5] type pointer. You then add 1 to this pointer - because of pointer arithmetic this new pointer pasts to the byte just after 5 in memory. Then you typecast (required, this time) and assign this value to ptr.
You subtract 1 from ptr and then dreference and print. ptr is a char *, so this subtraction simply moves the pointer back by one from "one past the end of a" to point to the last element of a. Hence you get the 5.
Finally, the reason char *ptr=&a+1; gives a warning is because C requires conversions between pointer types to have an explicit cast. As mentioned above, &a is of type char (*)[5], not char *, so to assign that value to a char * variable, you'll need the explicit cast.
Since you seem totally new to it let me explain it to you in simple terms instead of going for the rigorous explanation.
You see, for your program above, a and &a will have the same numerical value,and I believe that's where your whole confusion lies.You may wonder that if they are the same,the following should give the next address after a in both cases,going by pointer arithmetic:
(&a+1) and (a+1)
But it's not so!!Base address of an array (a here) and Address of an array are not same! a and &a might be same numerically ,but they are not the same type. a is of type char* while &a is of type char (*)[5],ie , &a is a pointer to (address of ) and array of size 5.But a as you know is the address of the first element of the array.Numerically they are the same as you can see from the illustration using ^ below.
But when you increment these two pointers/addresses, ie as (a+1) and (&a+1), the arithmetic is totally different.While in the first case it "jumps" to the address of the next element in the array, in the latter case it jumps by 5 elements as that's what the size of an array of 5 elements is!.Got it now?
1 2 3 4 5
^ // ^ stands at &a
1 2 3 4 5
^ // ^ stands at (&a+1)
1 2 3 4 5
^ //^ stands at a
1 2 3 4 5
^ // ^ stands at (a+1)
The following will give an error about unspecified bound for array as not explicitly specifying the size as below means the program won't know how many elements to "jump" to when something like (&a+1) is encountered.
char a[]={1,2,3,4,5};
char *ptr=(char *)(&a+1); //(&a+1) gives error as array size not specified.
Now to the part where you decrement the pointers/addresses as (ptr-1).In the first case, before you come to the decrement part, you should know what happens in the statement above it where it is cast to type char*:
char *ptr=(char *)(&a+1);
What happens here is that you "strip off" the original type of (&a+1) which was type char (*)[5] and now cast it to type char* which is the same as that of a,ie, the base address of the array.(Note again the difference between base address of an array and address of an array.So after the cast and assignment in the above statement,followed by the decrement in printf(), ptr now gives the memory location right after the last element of the array, which is 5.
1 2 3 4 5
^ // ^ stands at location of 5, so *ptr gives 5
So when you dereference the pointer ptr after decrementing it as *(ptr-1) it prints the value of 5 as expected.
Now finally, contrast it with the second case where 1 is printed.Look at the illustration I have given using the symbol ^. When you had incremented a as a+1, it points to the second element of the array, ie 2 and you had assigned this address to ptr.So when you decrement ptr it as (ptr-1), it jumps back one element and now points to the first element of the array ,ie 1.So dereferencing ptr in second case gives 1.
1 2 3 4 5
^ // ^ stands at address of 1, so *ptr gives 1
Hope this made it all clear.
The difference is in the type of the pointer that you get:
Array name a by itself represents a pointer to the initial element of the array. When interpreted in that way, e.g. in an expression a+1, the pointer is considered to point to a single character.
When you take &a, on the other hand, the pointer points to an array of five characters.
When you add an integer to a pointer, the number of bytes the pointer is moved is determined by the type of the object pointer to by the pointer. In case the pointer points to char, adding N advances the pointer by N bytes. In case the pointer points to an array of five chars, adding N advances the pointer by 5*N bytes.
That's precisely the difference that you are getting: your first example advances the pointer to the element one past the end of the array (which is legal), and then move it back to the last element. Your second example, on the other hand, advances the pointer to the second element, and then moves it back to point to the initial element of the array.
What you are running into is a subtlety of pointer arithmetic.
The compiler treats "a" as a pointer to char - an entity that is 1 byte in size. Adding 1 to this yields a pointer that is incremented by the size of the entity (i.e. 1).
The compiler treats "&a" as a pointer to an array of chars - an entity that is 5 bytes in size. Adding 1 to this yields a pointer that is incremented by the size of the entity (i.e. 5).
This is how pointer arithmetic works. Adding one to a pointer increments it by the size of the type that it is a pointer to.
The funny thing, of course, is that when it comes to evaluating the value of "a" or "&a", when dereferencing, they both evaluate to the same address. Which is why you see the values that you do.
Arrays "decay" into pointers to the first element. So taking the address of a gives you a pointer to an array of 5 chars, which is like declaring a char[][5]. And incrementing this pointer advances to the next element of the char[][5] array - that is 5 characters at a time. This is different from incrementing the pointer that decays from the char[5] array - that is, one character at a time.

About pointers in C

I started to read a few articles about pointers in C and I've got one example that I don't understand.
The example is from here: http://en.wikibooks.org/wiki/C_Programming/Pointers_and_arrays
Here it is:
Let's look at a slightly different problem. We want to have a two dimensional array, but we don't need to have all the rows the same length. What we do is declare an array of pointers. The second line below declares A as an array of pointers. Each pointer points to a float. Here's some applicable code:
float linearA[30];
float *A[6];
A[0] = linearA; /* 5 - 0 = 5 elements in row */
A[1] = linearA + 5; /* 11 - 5 = 6 elements in row */
A[2] = linearA + 11; /* 15 - 11 = 4 elements in row */
A[3] = linearA + 15; /* 21 - 15 = 6 elements */
A[4] = linearA + 21; /* 25 - 21 = 4 elements */
A[5] = linearA + 25; /* 30 - 25 = 5 elements */
A[3][2] = 3.66; /* assigns 3.66 to linearA[17]; */
A[3][-3] = 1.44; /* refers to linearA[12];
negative indices are sometimes useful.
But avoid using them as much as possible. */
My question is why A[0] is a pointer only to five elements and not to ALL of linearA, since the name of an array is a pointer to its first member.
And A[1] = linearA + 5; is 6 elements in a row -- for the same reason? Isn't A[1] supposed to be a pointer to the 6th member of linearA?
Can someone explain where is my mistake?
Except in a few exceptions, in C an array name is converted to a pointer to the first element of the array. linearA is an array 30 of float and in the expression:
A[0] = linearA;
it is converted to a pointer to float.
A is an array 6 of pointer to float. The element of A are of type pointer to float. So A[0] is a pointer to float and not a pointer to an array.
And A[i][j] in C is equivalent to *(A[i] + j) so A[i][j] is a float (dereferencing a pointer to float yields a float).
A[0] is a pointer to the 1st element of linearA. Since linearA is a contiguous array, this pointer actually allows to access any of the linearA 30 elements by adding an appropriate offset. However in this piece of code you emulate a 2D array by pointing to different offsets in the linearA array. The result is 2D-like array addressing: A[n] brings you to the location (i.e. offset in the linearA) of your n-th row and A[n][m] brings you to the m-th element inside this row.
My question is why A[0] is a pointer only to five elements and not to
ALL of linearA, since the name of an array is a pointer to its first
member.
you setup A[0] to point to linearA which is the first float in the array, A[0] is a pointer and thus doesn't know anything about what it points to part from an address. So A[0] is not a pointer to only five elements it points to where the array starts and has no concept of where the array ends.
And A[1] = linearA + 5; is 6 elements in a row -- for the same reason?
Isn't A[1] supposed to be a pointer to the 6th member of linearA?
yes A[1] points to the sixth element but as said before its a starting address.
It's because this line sets up an array of 6 pointers to float:
float *A[6];
And this line sets the first of those pointers to the first element of the 30.
A[0] = linearA;
Therefore each element of A points to a subsection of the original array. You have to assign them though - they'll initially point to random addresses.
The first one is the initial address (&linearA[0]) and the next five are the following ones. These are accessible as A[0][0] to A[0][5]. Because of the way arrays correspond to pointers, you can keep going up, so long as you don't exceed the 30th.
But you can assign A[n] to any part of the array you like. As long as it's part of the original array, it will point that member, and the next 5 (or however many you want).
For example, by pointing A[1] to &linearA[6], you would effectively be setting up a two dimensional array (it would resemble one, but not behave as one).
The example you posted shows a somewhat esoteric technique called Iliffe vector, which is one possible way to implement jagged arrays in C. A jagged array is a matrix in which each row has a different length.
Since arrays are one-dimensional in C, you are creating a single array linearA containing all the elements, which is interpreted as a sequence of rows, each of a different size. The pointer array A contains pointers to the first element of each row that allow you to access elements using row and column indices.
The code displays several interesting features of C pointers and arrays:
linearA + 5
Pointer arithmetic: adding an integer to a pointer (or array) gives you a pointer pointing n elements after the original pointer.
A[3][2] = 3.66;
This nice syntax allows you to think of this structure as a two-dimensional matrix.
Also, and this is probably the main point of the example, pointers and arrays are interchangeable. Here, A[3] is a pointer to float, since A was defined as an array of pointers to floats; appending [2] gives us the element 2 places after the one pointed by the original pointer. This is similar to the pointer arithmetic above, only in this case the pointer is dereferenced. Actually, array access is defined in terms of pointers so X[5] is equivalent to *(X+5).
A[3][-3]
This shows that there is nothing stopping you from accessing an element outside of a given row. In this case, you are accessing the element 3 places before the one pointed by A[3]. This is something that is rarely needed, and it only works in this case because you built the matrix to have contiguous elements. Usually, accessing elements outside the allocated range of an array will crash your program.
Finally, to answer your question:
And A[1] = linearA + 5; is 6 elements in a row -- for the same reason? Isn't A[1] supposed to be a pointer to the 6th member of linearA?
As pointers and arrays are interchangeable, A[1] is both a pointer to the sixth element in linearA and an array starting from the sixth element in linearA. There is nothing in the language saying that the latter is 6 elements long, you have to implement that logic in your code.

Resources