Accessing array elements in c - c

Below is the code on compiling this code in codeblocks I get the following error message:
1 value required as increment operator.
Now I know that arr++ is not working but I want to know why.
#include<stdio.h>
int main()
{
int arr[5]={1,2,3,4,5},i;
for(i=0;i<5;i++)
{
printf("%d\n",*arr);
arr++;
}
return 0;
}

arr++ is not working but i want to know why?
arr stores the base address that is &arr[0] therefore, arr always points to the starting position of the array and can't be changed. that's the reason why arr++ is invalid and doesn't work.
Solution:
you can instead use arr with the help of * (referencing operator) operator to print the array elements
for(i=0;i<5;i++)
{
printf("%d\n",*(arr+i));
//pointer arithmetic *(arr+i)=*(&arr[0]+i*sizeof(data_type_of_arr))
}
here, pointer arithmetic is helpful to understand
or else, in order to print the data instead use the index i this way :
for(i=0;i<5;i++)
{
printf("%d\n",arr[i]);
}
One more way to do it is to consider a new pointer to &arr[0] and increment.
int *p=&arr[0];
for(i=0;i<5;i++)
{
printf("%d\n",*p);
p++;
//pointer arithmetic *(p)=*((&p)+1*sizeof(data_type_of_arr))
//NOTE: address of p updates for every iteration
}
For further reading on pointer arithmetic : here

While arrays can decay to pointers to their first element (which is what happens when you use e.g. *arr) it is not a pointer in itself.
You also can not change an array, change where it "points", which is what is wrong with arr++, it is roughly the same as arr = arr + 1 and while arr + 1 is allowed the assignment back to arr is not, you can't change the location of an array.
If you want to do like you do, then you need an actual pointer, initialize it to point to the location of the first element of arr, and use the pointer in the loop instead.

#include<stdio.h>
int main()
{
int arr[5]={1,2,3,4,5},i;
for(i=0;i<5;i++)
{
printf("%d\n",*(arr+i));
}
return 0;
}
arr++ not working.because of array is constant pointer and you can't increment the address. so alway remember array name represent as base address then If you want to increment then give extra argue with that.see the above example.

The increment operator is applied on the value of a variable. The value of an array is its elements, so what would you expect the increment operator to do? Increment each element in the array? The value of a pointer variable, on the other hand, is an address, so the increment operator applies here.

You can't using operator ++ for arrays.
Array is are constant pointer to data and can't be modified.

Related

terminating array looping using pointer notation in C

I’m taking a C class on Udemy. Unfortunately the instructor isn’t replying to my question so I thought I’d try this site. My assumption is that it is probably fairly common when developing a program to not know how many elements may be part of an array. When initializing an array the instructor recommends not specifying a size but to let the compiler do it.
Example: int array[ ] = {2,3,4,5,6,7,8};
Obviously, using this method there is no index to use to terminate looping. According to “C Primer Plus” by Stephen Prata the element after the last element in the array is a valid pointer location:
(pg. 406) - C guarantees that when it allocates space for an array, a
pointer to the first location after the end of the array is a valid
pointer.
If I’m using pointer notation (array++) to loop through the array, what condition can I use to terminate the looping? Is there a value in that location after the final element that I can use? Is that value always the same or does it change depending on the type of array?
In C pointers are signed. That has consequences dealing with array-like data structures where you might:
while (a <= a+last) {
...
a++;
}
if the index one beyond the end of a could have a change of sign, then that code could fail. Idiomatic C does not suggest the above; but it needs to be preserved, thus this limitation.
In system code, it is possible that you deal with allocations that do not conform to this, thus you should try to work with the idiomatic:
while (a < a+len) {
...
a++
}
So, for your exact question:
for (size_t i = 0; i < sizeof array/sizeof array[0]; i++) {
...
}
or
for (int *p = array; p < array + sizeof array / sizeof array[0]; p++) {
...
}
Your basic idea (looping through an array using pointers) is sound; however, there are a number of points in your question that need some attention.
Is there a value in that location after the final element that I can use? Is that value always the same or does it change depending on the type of array?
Yes, there is a (almost certainly) some value in that location, but it's not something you can ever use! The pointer to the 'one-past-the-end' element is valid only for use in pointer arithmetic or comparison operations; attempting to dereference it (to read the value at that address) is undefined behaviour.
You can get that 'one-past-the-end' pointer by adding the number of elements in the array to the address of the array's first element (or the array 'name' itself). The idiomatic way to get the number of elements in an array is to divide the size of the entire array by the size of its first element. So, for your array, we can declare and initialize our "end pointer" like this, using the sizeof operator:
int* end = array + sizeof(array) / sizeof(*array);
// int* end = array + sizeof array / sizeof *array; // Alternative form: "()" optional
Another important point: In your question you mention using array++ to loop through your array variable. You cannot do this, because array isn't actually a (modifiable) pointer variable – it's the name of a variable (an array) whose location is fixed at the point when main (or whatever function it is declared inside) is entered. Instead, you will need to copy the address of the array into another int* pointer, and increment that in the loop.
With those points in mind, here's an illustrative example of how you can loop through your array using a pointer:
#include <stdio.h>
int main(void)
{
int array[] = { 2,3,4,5,6,7,8 };
int* end = array + sizeof(array) / sizeof(*array);
for (int* p = array; p < end; ++p) {
// Note that, when we reach p == end, the loop will not run, so ...
printf("%d\n", *p); // ...we never attempt the *p operation on that
}
return 0;
}
A couple of other points of clarification:
The int* p = array assignment works (and is perfectly valid C) because an array variable name can readily decay into a pointer to its first element (as it will if you pass that array as an argument to a function, for example). See: What is array to pointer decay?
Because of that last point above, you cannot use the sizeof(a)/sizeof(*a) paradigm to determine the size of an array in a function it is passed to as an argument; in such cases, you need to pass the array's size as an additional argument. See: How do I determine the size of my array in C?

Difference between **(x+i) and *(*x+i)

I'm using an array of pointers where each index holds a pointer that points to an array of integers. While I was able to figure out how to print the values in an array using the pointer array, there is one line of code that I need clarity on. I want to understand the difference between **(x+i) and *(*x+i) as the former throws a Segmentation fault exception while the latter prints the desired output. Please refer to my example code below.
int pointer_array=malloc(1*sizeof(int*));
int number_array = malloc(2*sizeof(int));
*(pointer_array)=number_array;
for(int i=0;i<2;i++) {
*(pointer_array+i)=i;
}
for(int i=0;i<2;i++) {
//printf("\n%d",**(pointer_arr+i)); This throws Segmentation Fault exception
printf("\n%d",*(*pointer_arr+i)); // This prints the desired output 0 \n 1
}
The difference between the expressions becomes very clear if we convert them to array notation by making use of the *(a + i) == a[i] equivalence and its corollary *a == a[0].
**(x + i) is x[i][0], whereas *(*x + i) is x[0][i].
In your code we want this:
#include <stdlib.h>
int **pointer_array = malloc(1*sizeof(int*));
^^
int *number_array = malloc(2*sizeof(int));
^
Then the rest of the code means this:
*(pointer_array)=number_array; // pointer_array[0] = number_array
Oops: the loop assigns integers to pointers:
for(int i=0;i<2;i++) {
*(pointer_array+i)=i; // pointer_array[i] = i
}
The above is probably intended to be number_array[i] = i.
for(int i=0;i<2;i++) {
printf("\n%d",*(*pointer_arr+i)); // printf ... pointer_arr[0][i]
}
If we correct the first loop to initialize number_array, then this second loop should retrieve those values.
Otherwise we are marching over uninitialized values.
**(x+i) means "evaluate x+i, which will give a pointer, then read the value that it points to, which will give another pointer, then read the value that it points to", or equivalently, x[i][0]. *(*x+i) means "evaluate x, which will give a pointer, then read the value that it points to, which will give another pointer, then add i to that, then read the value that it points to", or equivalently, x[0][i]. Obviously, these are very different expressions.
Your code is unsafe; malloc will return a void * — a pointer type. You are storing the results in an int. An int is not guaranteed to be large enough to store a void * and indeed won't be on x86, the current predominant architecture.
That being said:
(x+i) if x is a pointer will evaluate to i*sizeof(*x) + x. So it'll evaluate to a pointer that is i slots after x;
**(x+i) will therefore read the pointer from i slots after x and then read whatever that pointer points to.
So from an array of pointers to arrays, it will read the first item from the ith array.
Whereas:
*x+i will read a pointer from x and then add i*sizeof(**x) to it;
*(*x+i) will read a pointer from there and dereference it.
So from an array of pointers to arrays, it will read the iith item from the first array.

Why is the declaration *(*(arr+1)+2) not working when I am passing the a 2d array to a function (tes).t

#include<stdio.h>
int test(int *x);
void main(){
int arr[2][3], a;
arr[1][2] = 2;
printf("%d\n", test((int *)arr));
printf("%d\n", *(*(arr+1)+2));
}
int test(int *prr){
int a;
a = *(*(prr+1)+2);
return a;
}
The above code is giving me the following error:
error: invalid type argument of unary ‘*’ (have ‘int’)
a = *( *(prr+1)+2);
^
but the same declaration works in the main function:
printf("%d\n", *( *(arr+1)+2)).
Also when I replace it with *((arr+1*3) + 2), 3 being the size of 2nd dimension, in the function test, it worked and I could not understand how ??? I really want to know the reason. please help!!!
And why is their a need to type cast a 2D array, but not 1D array when passing to a function.
I used the help of http://www.geeksforgeeks.org/pass-2d-array-parameter-c/, but the reason was not there.
In main function arr is an array of arrays of int. *(*(arr+1)+2) is equivalent to *(arr[1] + 2) = arr[1][2]. arr[1] is an array and will decay to pointer to first element arr[1][0].
In test, prr is a pointer to int. *(prr+1)+2 is equivalent to *(prr[1] + 2). prr[1] is an int. This makes the expression prr[1] + 2 an int. Operand of unary * operator must be a pointer variable.
Change function prototype to
int test(int x[][3]);
and make function call as
printf("%d\n", test(arr));
in function test(int *prr) prr points to a integer not a array.
so *(Prr+1) is a integer, but '*' unary operator is only applied to pointers.
Okay, a quick short lesson on arrays and pointers.
Thumb rule 1: Arrays and pointers are almost always interchangable but there are exceptions!
Taking a 1-D array, we can declare it like this :-
int arr[10];
This declares a variable named arr which can hold 10 integer elements.
I can similarly use the pointer notation to represent this array using a pointer variable or by using the array name (arr) itself.
printf ("%d", arr[2]); // Array method : will print out the third element, indexing starts from 0
Thumb rule 2: Array name(be it 1D 2D 3D 4D) always decays into a pointer or an address.
printf ("%lu", arr) //will print out the base address of the array, i.e address of the first element
How to print the value using a pointer ? Simply, dereference it using * operator.
printf("%d", *arr) //Pointer notation - will print the first value
How to reference the array using another variable?
int *ptr = arr; //Pointer notation - just simply write the array name as it decays into an address
printf("%d", *ptr); //Pointer notation - prints the first element
Many people say int *ptr is pointer to an array.
In reality it's not. It's actually a pointer to an integer not an array. Why?
Because in the first place we are storing the address of the first integer of the array and then we can traverse it by incrementing the pointer. So, in real pointer is storing the address of an integer(First integer).
Now, coming to 2D arrays :-
Declaration:-
int arr[2][3]; // arrays of 2 rows and 3 columns, total 6 elements
Same above rules implies :-
printf("%d", arr[0][1]); //prints the second element of the first row.
printf("%lu", arr) //prints the base address of the 2D array
Coming to Pointer Notation :-
printf("%d", *(*(arr + 0) + 1); // how this works?
arr contains the address. Adding a integer to it with make you jump to that row.
arr + 1 // gives the second row, i.e. arr is currently pointing to the first element of second row.
Now, further adding an integer to it, will make you skip to that specified column in that particular row.
((arr + 1) // second row + 2 ) // will you skip to third element of the second row
This is the implicit pointer notation that language gives you, when you choose to treat the array name as a pointer.
Now coming to your problem : - Explicit Pointer Notation:-
What are you trying to achieve is, storing the base address of the 2D array in a pointer.
How to correctly do that ?
int (*ptr)[3]; //reading it goes like this - ptr is a pointer to a 1D array of 3 ints
The 3 here specifies the number of columns your 2D array has.
So what it is doing is, trying to store the base address of first 1D array of that 2D array (which means 0th row base address) into the pointer.
The rest remains the same.
int (*ptr)[3] = arr; // storing the 2D array in ptr
Now, you can use it as a normal pointer(Pointer notation applies on it)
(ptr + 1) //now ptr is pointer to the Second 1D array of that 2D array or you can say to the second row's first element.
Another way you can catch an array in a function is like this:-
I use it very less though.
int main()
{
int arr[2][2];
fun(arr);
}
void fun(int catch[][])
{
}
// This is simple to understand and as well as to relate. Now, again catch can be used as pointer or as an array. It depends on you :)
void fun1(int (*ptr)[2])
{
//my way
printf("%d", ptr[1][1]);
printf("%d", *(*(ptr + 1) + 1));
//answer will be the same
}
//Ptr now contains that 2D array base address, again can be used as an array or a pointer :)
In you function main arr is a 2-d array of int and thus, this works -
printf("%d\n", *(*(arr+1)+2)); // you dereference it twice to get value
But in your function test, parameter is of type int * and therefore , this expression -
a = *( *(prr+1)+2); // prr is of type int *
gives error as you try to dereference int * twice. There is only one level of indirection , so you need to dereference once. Also, you could achieve same by passing 2-d array directly without cast and it would work.
Something like this -
int test(int **prr){
// you code
}
and in main you can call it like this -
int x = test(arr);

Explanation of code snippet regarding how to pass an array as a function argument using a pointer?

Following is the CODE SNIPPET to add elements of an array in C language!
Main function :
int main ()
{
int a[3]={10,11,12};
printf("%d\n" , arraysum(a,3) );
}
Arraysum function definition :
int arraysum (int *addr , int len )
{
int sum = 0, i ;
for (i=0 ; i<len ; i++)
sum += addr[i];
return sum ;
}
OUTPUT : 33
QUESTIONS : I know that in the main function the base address of the array a is passed to pointer addr , but after that I am unable to understand how following statement is working :
sum+=addr[i];
Q1 : Next , addr was a pointer variable , then how am I using it as an array in arraysum function ?
Q2 : More importantly when I passed base address of array a to the pointer then how come i am able to access all the elements of array a through it ?
Q1 : Next , addr was a pointer variable , then how am i using it as an array in arraysum function ?
Actually, you have this backwards. The subscript operator [] applies to pointers, not to arrays. Huh? What am I on about? Well when you do array[i] where array is an array, the array actually decays to a pointer to its first element. So you are always applying [] to a pointer. In your case, addr is already a pointer to its first element.
Q2 : More importantly when i passed base address of array a to the pointer then how come i am able to access all the elements of array a through it ?
When you do something[i], it is equivalent to *((something) + (i)). This is just basic pointer arithmetic. Take the pointer pointing at the first element, increment the pointer by i, then dereference it.
It is because of this pointer arithmetic that we can access all of the elements of an array through a pointer to one of its elements.
Q1: You can index pointers as if they were arrays (in fact, array indexing really is pointer indexing). So
addr[i]
is the same as *(addr + i)
Q2: because when you pass an array to a function expecting a pointer, the array decays to a pointer to its first element. So addr points to the first element of a. This is a simplified version of the same phenomenon, without a function call:
int a[] = {1, 2, 3}; // size 3 array of int
int * p = a; // OK: a decays to int*. p points to &a[0]
p[0]; // same as a[0]
Note that despite everything, a and p have different types. a is a size 3 array of int. The type contains size information. p is just a pointer to int. It can point to an element of an array, but it can also point to a single int.
Basically int *addr point to the first element in your array. So if you say addr[i] it equals to *(addr + i), which points to the ith element.
When you pass plain array to function, it decays to a pointer. So, we would talk about pointer from now onwards.
If you get a pointer to memory location (ptr) what all things you could do with it:-
de-reference it
*ptr
increment it
++ptr;
etc...
So, this function doesn't know you have an array. You happen to behave in this function as this pointer is pointer into as array. That means you can increment it to get to the next element of an array as array elements are in consecutive memory location. However, you have to ensure that you don't cross the bound. For that you explicitly pass size of array to this function.

the difference between array identifier and address of array identifier

Following program would state my doubt clearly I think,so I posted the program:
#include <stdio.h>
int main() {
int a[]={1,2,3,4,5};
if(&a[0] == a)
printf("Address of first element of an array is same as the value of array identifier\n");
if(&a == a)
printf("How can a value and address of an identifier be same?!");
return 0;
}
This is the link to output: http://ideone.com/KRiK0
When it is not the subject of the sizeof or unary & operators, an array evaluates to a (non-lvalue) pointer to its first element.
So &a is the address of the array a, and a evaluates to the address of the first element in the array, a[0].
That the address of the array and the address of the first element in the array are the same is not surprising (that is, they point to the same location even though they have different types); the same is true of structs as well. Given:
struct {
int x;
int y;
} s;
Then &s and &s.x point to the same location (but have different types). If converted to void * they will compare equal. This is exactly analogous with &a and &a[0] (and consequently just a).
C++ has an implicit conversion between an array reference and a pointer. This has been asked many times before, see for example this SO question.
In C, you can get away with comparing two different types of pointers, but your compiler should give you a warning.
If I get your question right. Your int a[]={1,2,3,4,5}; I believe only stores the address of element 0 so putting this if(&a[0] == a)
is probably not required. The c string theory states that an array identifier without the bracket is the address of the first element of the characters. "a" is not defined in the program. it would probably give you a stack error. I would write it this way if(&a == a[]){printf("------"); this would only compare the address of the pointer to the address of the first element of the array.

Resources