dreferencing 2 d array - c

Please look at this peice of code :-
#include<stdio.h>
int main()
{
int arr[2][2]={1,2,3,4};
printf("%d %u %u",**arr,*arr,arr);
return 0;
}
When i compiled and executed this program i got same value for arr and *arr which is the starting address of the 2 d array.
For example:- 1 3214506 3214506
My question is why does dereferencing arr ( *arr ) does not print the value stored at the address contained in arr ?

*arr is type integer array of length 2, so it shares the same address as arr. They both point to the beginning of their arrays, which is the same location.

in C, a 2d array is not represented in memory as an array of arrays; rather, it is a regular 1d array, in which the first given dimension is needed in order to calculate the right offset within the array at execution time. This is why in a multi-dimensional array you always need to specify all the dimensions except the last one (which is not required); for example, if you declare an array like
int a[2][3][4];
the array would be represented in memory as a single array of 2*3*4 elements in total. Trying to access the element at position (i,j,k), will actually be translated into accessing the element 3*i+4*j+k in the plain array. In some sense, the initial dimensions are needed to know where to put "row breaks" in the 1d array.

Related

C programming with pointers

Write a program that creates a random array of 20 integers with a pointer that initially points to the first element of the array. The program will have a while loop that allows the user to do any of the following:
print the array of numbers with the pointed to number highlighted in some way
move the pointer left or right a certain number of items in the array
change the value of the pointed to number
quit the program
All the changes to the list of numbers must be done with pointers (not by referencing the array index),
I have this to start off which is just setting up the array
#include <stdio.h>
#include <stdlib.h>
int main{
int array[20];
for(int i=0; I<20;i++){
array[I]=rand() % 100;
}
int pointer=&array[0];
int i=0;
return 0;
}
I would really appreciate the help
"with a pointer that points to the first element of the array"
Basically means you need to dynamically allocate memory. A memory block that is allocated always return a pointer to the first element of the array:
int* array = calloc(sizeof(int)*20);
// Allocate memory for 20 integers ^
Now you have an array of 20 integers and array points to it's first element. Then, if we don't actually want to reference the index.
*(arr+1)
Will give you the value of the second element since it evaluates to arr[1].
To print them using a while loop, use an integer to keep track of the current index and while(array+index) print it and increment index.
This is so because memory of a computer is like a street with different houses with an integral number along it.

Can someone explain this behavior?

I write a simple code that get's a matrix of maximum M lines and I can't understand why it is giving me a strange output :
for M=50 :
"the cell [1][0] is : 17273520" (I get random outputs every time)
for M=4 :
"the cell [1][0] is : 0" (always)
#define M 50
void printImage(int a[][M]){
printf("the cell [1][0] is : %d",a[1][0]);
}
int main(){
int a[3][4] = {0};
printImage(a);
}
Can anybody explain what exactly is for M ? how it works ?
and how can I make the function work for matrices that has less than M lines ?
A two dimensional array a in C is an array of arrays. Each member of a therefore has to be of the same size. The second size parameter in the definition is that size.
What you pass to printImage is a two dimensional array that decays to a pointer. It points to the first array element of a.
Now, since multidimensional pointer arithmetic a[i][j] for a true two dimensional array is *(a + i * M + j) we see that M is part of the type definition.
If you specify that you will pass a[][50] but in fact pass a[][4], the indexing for a[1][0] will be way outside the array bounds.
Since accessing outside of an array boundary is undefined behavior, anything can happen, you get some random value. But the program can just the same crash or format you hard-drive.
This is also why you should always build your programs with as high a warning level as possible (even turn most into hard errors). For instance, GCC can protect you with the following helpful diagnostic:
error: passing argument 1 of 'printImage' from incompatible pointer type [-Wincompatible-pointer-types]
If you need for the array elements of the two dimensional array to be of different sizes. You can specify that the function accepts a variable length array. Pass the size of the array dimensions first, and then the array with these dimensions:
void printImage(size_t n, size_t m, int a[n][m])
{
// a is a VLA with dimensions specified by n and m
// pointer arithmetic will be *(a + i * m + j)
}
The above is valid C99.
You define a as array a[3][4] but in printImage you tell your compiler that the last dimension is 50 instead of 4.
With that you mess up memory map of your array and the compiler reads wrong memory location which is far behind the array.
You should always use the correct size.
This could be done like this:
int a[3][M];
in main().
You've defined a matrix with dimensions 3x4, altogether 12 ints. But in the function, you've defined the second dimension to be 50, which exceeds the real dimension. When you try to read a value from [1][0] it goes to position 50 which is very far from the last initialized value in position 11. That is why you get some random value.

Number of array elementsbof dynamic allocated array in C

I have problems finding the number of array elements in my dynamical allocated array.
If I have a normal Array I know how to find out how much elements are in there with:
int array[] = {1,2,3};
printf("Number of array elements: %i\n",(int)(sizeof(array) / sizeof((array)[0])));
this prints me:
Number of array elements: 3
But when I want to dynamically allocate an array and know its size I can't get it working the same way:
int *array;
array = malloc(3*sizeof(int));
printf("Number of array elements: %i\n",(int)(sizeof(array) / sizeof((array)[0])));
This always gives me:
Number of array elements: 2
No matter how much how small or big I make the allocation it always prints
2
Please can someone help?
The reason you see different size is because the underlaying data isn't the same.
In you first example, you have statically compiled array of integers. This array elements are all aligned in memory and array is the array. Using sizeof(array) allows you to get the overall size of this array.
In the second example, you have a dynamically allocated pointer on an array of integers. This is totally different in memory. The array variable isn't the array practically speaking. It's the pointer to the first element. Using sizeof(array) here returns the size of the pointer on the first element, hence 8.

Why Do I need that extra asterix using 2D array?

I know that if arr is an array then arr[i]=*(arr+i); and if is a 2D array then arr[i][j]=*(*(arr+i)+j); So I have this code
main(){
int arr[5][5];
int arr2[25]; // same as arr[5][5];
int i,j;
for(i=0;i<5;i++)
for(j=0;j<5;j++){
arr[i][j]=i+j;
printf("arr[%d][%d] is at %p\n",i,j,&arr[i][j]);
}
printf("*(arr+i)=%d\n",*(arr+1)); // why this dont work
for(i=0;i<24;i++){
arr2[i]=i;
printf("arr2[%d] is at %p\n",i,(arr2+i));
}
printf("*(arr+i)=%d\n",*(arr2+1)); // prints 1 as expected
}
I know that in C there's no such thing as 2D array, its basically a linear row major contiguous blob of memory. So I'm wondering why I cant print the value of 2D arr using *(arr+1), which means add 1*5*4 bytes to the base of arr and dereference the value at that address. I know that **(arr+1) works but I dont know why I need that extra asterix ? Also If I do this printf("*(arr+i)=%p\n",*(arr+1)); is the same as I would use (arr+i) to interpret as an address
arr is an array of arrays of ints. Its type is int [5][5]. So, the elements of arr is 1D arrays. When used in expression, in most cases, arrays converted to a pointer to its first element. In *(arr + 1), arr is converted to pointer to arr[0], i.e, first 1D array. Adding 1 will increment it by 5*4 = 20 bytes, i.e, next element of array arr which is arr[1].
Since arr[1] is an array, it can't be printed (as a whole), but its address can be. arr[1] is itself an array and it will decay to pointer to its first element, i.e, arr[1][0]. To print its element you need another dereference which is acheived by arr[1][j] (j is columns).
arr[1][j] is equivalent to *(arr[1] + j) which is ultimately equivalent to *(*(arr + 1) + j).
Suggested Reading: What exactly is the array name in c?
As you said, a 2D array in C is basically an array of 1D arrays. You might think of this as an array of rows.
The rightmost * will dereference the outer array, selecting the row you want.
*(arr+i) //this gives me a pointer to the row I want
The * to the left of that will dereference in the inner array, selecting an element from the row.
*(*(arr+i)+j) //this gives me an element in the row
**(arr+i) is just a special case of the above where the column number j is 0.
The type of *(arr+1) = the type of arr[1] = int [5], which will decay to int* when used in printf.
To print the pointer, use:
printf("*(arr+i)=%p\n", *(arr+1));
To print the object it points to, use:
printf("*(*(arr+i))=%d\n", *(*(arr+1)));
You can make your code easier to read by using:
printf("arr[1] = %p\n", arr[1]); // Print the pointer
printf("arr[1][0] = %d\n", arr[1][0]); // Print the value

Why my 2D array is not functioning right?

I am newbie in C programming.I want to print 2 as my first element is 2 in the 2D array.But as i knew that n holds the first address of the array so *n should print the first element that is 2.My code
‪#‎include‬ <stdio.h>
int main()
{
int n[3][3]={2,4,3,6,8,5,3,5,1};
printf("%d\n",*n);
return 0;
}
why it is printing an address.Can anyone explain it to me??
A 2d array is just an array of arrays, so *n is actually the first subarray, to print the first element of the first subarray:
printf("%d\n", **n);
Or this is simpler and more clear:
printf("%d\n", n[0][0]);
You need to declare your array like this:
int n[3][3]={{2,4,3},{6,8,5},{3,5,1}};
Note that the first [3] isn't necessary (but there's nothing wrong with specifying it). By the way, if you enable warnings, e.g. with gcc -Wall, the compiler will warn that there are missing braces in your initialiser.
Then to print the first value you can use:
printf("%d\n",n[0][0]);
Or, if you prefer:
printf("%d\n",*n[0]);
You have an array or arrays, so this takes the zeroth element (which is an array), then dereferences it to get the zeroth value.
I think that you got some warning on %d because you are not tried to print the value - just the address only.
For a 2D array, to get any value, you need to dereference twice. i.e **n.
*n is also suitable, but for a 1D array.
Here you can use either **n, *n[0] or n[0][0] instead of *n.
If n would have been an array of integers, *n would have printed the first integer, as you are expecting.
But n is not that. Is a 2-dimensional array. One way of looking at it would be: an array of arrays. So in fact *n is an array.
If you have an 1D array-
int n[9]={2,4,3,6,8,5,3,5,1};
printf("%d\n",*n);
Because If you dereference the 1D array it will fetch the element. Now It will print 2.
But
int n[3][3]={2,4,3,6,8,5,3,5,1};
It is a 2D array so you need to dererence two times. If you dererence one time it will fetch the address of the array only. n, n[0], *n, &n, &n[0] all will represent the starting address of it.
Try -
printf("%d\n",**n);
or
printf("%d\n",n[0][0]);

Resources