Can't understand exactly the pointers in 2d array - c

I have done something by looking to the internet but something is missing here is my code
void draw_way(int *arr,int lenght_row,int lenght_column) {
int s1 = 0, s2 = 0;
for (s1 = 0; s1 < lenght_row; s1++)
{
for (s2 = 0; s2 < lenght_column; s2++) {
if (*((arr + s1 * lenght_row) + s2) == 1)
{
printf("S");
}
else if (*((arr + s1 * lenght_row) + s2) == 2)
{
printf("G");
}
else if(*((arr + s1 * lenght_row) + s2) == 3)
{
printf("#");
}
else if (*((arr + s1 * lenght_row) + s2) == 4)
{
printf(".");
}
}
printf("\n");
}
it is actually printing a maze but is is not important. The thing I want to understand is why ı had to use *((arr + s1 * lenght_row) + s2) why this is not working if ı use *(*(arr+s1)+s2) what 'lenght_row' does.

For any array or pointer arr and index i, the expression *(arr + i) is exactly equal to arr[i].
If we do this translation for *(*(arr+s1)+s2) that would be (arr[s1])[s2] (or arr[s1][s2]). Since arr isn't a pointer to a pointer (or array of arrays) then arr[s1][s2] doesn't make sense.
Instead you kind of emulate a 2d array (array of arrays) using a array (whose first element is pointed to by arr) and use arithmetic to calculate the single index into this array.
This is very common for dynamically allocated memory, where instead of using a jagged array (using pointers to pointers) you use a single contiguous area or memory.
It might be easier to understand with an illustration...
Lets say we want a 2d array of 2 by 3 elements. We can create it using dynamic allocation as a jagged array:
int **arr;
arr = malloc(2 * sizeof *arr); // First dimension
for (size_t i = 0; i < 2; ++i)
arr[i] = malloc(3 * sizeof *arr[i]); // Second dimension
Since we have multiple allocations, there's no locality in the array, arr[0][2] might not be followed by arr[1][0]. Locality and having the 2d array being contiguous could be good for some algorithm and use-cases.
A contiguous 2d array would be an array of arrays like
int arr[2][3];
but this is harder to handle dynamically, so instead we allocate a single contiguous memory area of 2 * 3 elements:
int *arr;
arr = malloc(2 * 3 * sizeof *arr);
Unfortunately this can't be indexed in the same intuitive way as a jagged array or array of arrays (i.e. arr[0][1] isn't possible). But with some clever arithmetic it is possible: arr[row_index * row_length + column_index] will be like arr[row_index][column_index] (for a jagged array or array of arrays).

arr is a flat array, not a multi-dimensional array. It emulates a mult-dimensional array by way of passing in the grid size. So, if it was 5x2, then arr as a flat array would be 10 integers long, not an array of 5 rows of another array of 2 columns.
Hence, it uses simple pointer arithmetic to emulate the r,c dimensions by way of the flat array index calculation
((arr + s1 * lenght_row) + s2)

if you reduce number of paranthises it will easier to understand: if (*(arr + s1 * lenght_row + s2) == 2)
2D array has c columns and r rows. They are stored in the memory continuously row0 then row 1 them row2 ...
So to access the particular element (row, column) you need multiply row by 'r' (whics is how many elements we hae in the row and add column.

For starters the expression in if-else statements like this
if (*((arr + s1 * lenght_row) + s2) == 1)
is incorrect. There should be
if (*((arr + s1 * lenght_column) + s2) == 1)
The parameter arr declared like
int *arr
has the type int *. So dereferencing the pointer like *arr you will get an object of the type int for which you may not apply the dereferncing operator.
So this expression
*(*(arr+s1)+s2)
is incorrect. The sub-expression *(arr+s1) has the type int. So the second use of the operator * produce a compilation error.
In the shown function there is emulated a two dimensional array using a pointer to a one-dimensional array. That is the one-dimensional array is logically split into chunks by length_column elements.
Here is a demonstrative program.
#include <stdio.h>
#define ROW_LENGTH 2
#define COLUMN_LENGTH 3
void display( const int *arr, size_t row_length, size_t column_length )
{
for ( size_t i = 0; i < row_length; i++ )
{
for ( size_t j = 0; j < column_length; j++ )
{
printf( "%d ", *( arr + i * column_length + j ) );
}
putchar( '\n' );
}
}
int main(void)
{
int arr[ROW_LENGTH * COLUMN_LENGTH] = { 1, 2, 3, 4, 5, 6 };
display( arr, ROW_LENGTH, COLUMN_LENGTH );
return 0;
}
Its output is
1 2 3
4 5 6

Related

Printing a multidimensional array in C

I am trying to print a 2-D array in C by using pointers but I am not getting the expected output.
Program:-
#include <stdio.h>
int main()
{
int arr[2][3] = {{1,2,3},{4,5,6}};
int* p;
for ( p = arr; p <= arr+6; p++)
{
printf("%d ", *p);
}
return 0;
}
Output:-
1 2 3 4 5 6 -1116112128 1587637938 0 0 1893963109 32521 -1453950296 32766 -1453805568 1 800797033 21984 -1453949463
Could you tell me where I am wrong as the output should only be:
1 2 3 4 5 6
Could you tell me where I am wrong
The elements of arr are not integers, but arrays of 3 integers. So arr+6 is surely a different address than what you expect, since pointer arithmetic works in multiples of the size of the type in the array.
You'll always be better off using nested loops to iterate over a multidimensional array; treating it as one single-dimensional array of int leads to exactly the kinds of confusion you see here. The code is harder to understand and verify, it won't be any slower.
First, when looping through arrays of size n wth an index i, the condition for continuation should be i < n rather than i <= n, because array indexes in C run from 0 through n-1.
However, your code has a more serious error: 1-dimensional arrays can be 'decayed' into pointers to the elements' type; however, 2-dimensional arrays decay into pointers to 1-dimensional arrays. So, in your case, the type of the pointer used in the arr + 6 expression is a pointer to an array of three integers; further, when the 6 is added, that operation is performed in terms of the size of the pointed-to object, which is sizeof(int) * 3 – so, even when changing the <= to <, you will be running far beyond the actual bounds of the array.
To make the pointer arithmetic work in the correct 'units' (i.e. sizeof(int)), cast the arr to an int* before the addition (and also change the <= to <):
#include <stdio.h>
int main()
{
int arr[2][3] = { {1,2,3},{4,5,6} };
int* p;
for (p = (int*)arr; p < (int*)arr + 6; p++) {
printf("%d ", *p);
}
return 0;
}
You are trying to access the value in the wrong way, The two-dimensional array is saved as a continuous block in the memory. So, if we increment the value of ptr by 1 we will move to the next block in the allocated memory.
int arr[2][3] = {{1,2,3},{4,5,6}};
int *ptr = arr;
int i,j;
for (i = 0; i < 6; i++) {
printf("%d ", *(ptr + i));
}
return 0;
Array designators used in expressions with rare exceptions are implicitly converted to pointers to their first elements.
The type of the array elements of this array
int arr[2][3];
is int [3]. So a pointer to the first element of the array has the type int ( * )[3].
This assignment
p = arr;
where p has the type int * is incorrect because the operands of the assignment have incompatible pointer types.
At least you need to cast the right expression to the type int * like
p = ( int * )arr;
The same casting you need to use in the condition in the for loop. That is instead of
p <= arr+6
you have to write
p < ( int * )arr+6
Below there is a demonstration program that shows how to output a two-dimensional array as a two-dimensional array using pointers.
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int ( *p )[3] = arr; p != arr + 2; p++ )
{
for ( int *q = *p; q != *p + 3; ++q )
{
printf( "%d ", *q );
}
putchar( '\n' );
}
return 0;
}
If you want to output the two-dimensional array as a one-dimensional array then you can write
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int *p = ( int * )arr; p != ( int * )arr + 6; p++ )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
In
for ( p = arr; p <= arr+6; p++)
the expression arr, as an rvalue, is a pointer to the first element of the array (which is of type int [3], so each time you increment that pointer, it moves three int positions forward ---a whole row---, and so, arr + 6 points just after the sixth row of the array (if the array should ever had six rows) You can do it (with the proper explicit pointer conversions, as you are mixing pointers to int with pointers to int [3]) with the expression arr + 2 which is the addres of the first array element after the second row (and the number of rows of the array).
You can do it also declaring
int (*aux)[2][3] = &arr; /* aux is a pointer to the whole 3x2 array,
* so aux + 1 will be the position of the second
* 2D array after this one */
and then
int *end = (int *)(aux + 1);
or simply
int *end = (int *)(&arr + 1); /* see below */
(Beware that arr and &arr are both pointers and point to the same place, but they are not the same type (arr is of type int (*)[3] and &arr is of type int(*)[2][3])
So let's rewrite your code as
for (p = (int *)arr; p < end; p++)
or
for (p = (int *)arr; p < (int *)&arr + 1; p++)
would work, which seems more natural to do the calculus in complete array units than in rows or single cells (and you can change freely the dimensions of the array)
Your code would be:
#include <stdio.h>
int main()
{
int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
int *end = (int *)(&arr + 1); /* try to avoid evaluating this expression in the loop
* despite that it can be optimized to comparing
* with a constant value */
char *sep = "";
for (int *p = (int *)arr; p < end; p++)
{
printf("%s%d", sep, *p);
sep = ", ";
}
putchar('\n');
return 0;
}
(Beware that you have to use < operator and not <= as you don't want to print the value pointed by end, because it lies one place outside of the array)
Finally a note: this will work with true arrays, but not with function parameters declared as arrays, because they decay to pointers and then &arr is not a pointer to data the size of the array, but it is the address of the parameter itself, which points to the array somewhere else.

Create an array which contains elements of other arrays

Lets say I have two arrays, A[5] and B[3]. I want to create another array C[8] that will contain all the elements from A and B. First it will store A elements and then B. I am a beginner in C. So anyone can help?
You can use memcpy. Below I have assumed these are arrays of ints, but you could replace sizeof(int) with the type you are actually doing.
memcpy(C, A, 5 * sizeof(int));
memcpy(C + 5, B, 3 * sizeof(int));
The first line says copy 5 ints from the start of A to the start of C. The second line says copy 3 ints from the start of B to C starting at index 5.
Edit: As pointed out in the comments, I overcomplicated this. You can use the following and not have to worry about types:
memcpy(C, A, 5 * sizeof(C[0]));
memcpy(C + 5, B, 3 * sizeof(C[0]));
You can achieve this with two for loops. First copy the content from A to C:
for(int i = 0; i < 5; i++)
C[i] = A[i];
And then, copy the content of B to C, from the position where you inserted the last element of A:
for(int i = 5; i < 8; i++)
C[i] = B[i-5];
Note that the loop now starts with 5 and ends in 8, this is because we want to start copying the values of B into C after the positions already filled with the values of A. The position of B where we are reading is i - 5, which gives the positions 0, 1, 2... for B. We are doing this here because the loop starts in 5.
You can also do this with just one for loop in the following way:
for(int i = 0; i < 5; i++){
C[i] = A[i];
if(i < 3)
C[i+5] = B[i];
}
universal function
void *copy(void * restrict dest, const void * restrict src, const void * restrict src1, const size_t len1, const size_t len2, const size_t elemsize)
{
unsigned char *restrict ucdest = dest;
if(dest && src && src1)
{
memcpy(ucdest, src, elemsize * len1);
memcpy(ucdest + elemsize * len1, src1, elemsize * len2);
}
return dest;
}

In C/C++: How can i implement a 2D int array using two single pointers (no use of **int)?

I am exploring pointer "mechanics" in C/C++. I try to understand if and how is possible to implement a 2D matrix using two pointers (one for "rows" and one for "columns") instead of a single double pointer. I am aware that a matrix with rows*columns number of values could be stored in memory sequentially, but i am looking to comprehend deeper the mechanics of pointers and eventually to implement a function similar to
int value=getValue(vectorNr,vectorValue)
that is able to "simulate" the construct
value=Matrix[vectorNr][vectorValue]
vectorPointer vectorValue
| AddressV1 |------|valAddr11 valAddr12 valAddr13 |
| AddressV2 |------|valAddr21 valAddr22 valAddr23 |
| AddressV3 |------|valAddr31 valAddr32 valAddr33 |
I tried to begin writing a code like this but I quickly get stuck on pointer arithmetic and address offsetting. I also might chose a very dirty approach so any comment is welcome.
CODE TO IMPLEMENT A 2D ARRAY WITH POINTERS (BUT NOT USING DOUBLE POINTERS). To avoid confusion between rows and columns I refer to "Vectors as rows" and "Columns as vector values"
int vectorsNumber = 3; //Number of Vectors
int valuesNumber = 3; //Number of values stored in one Vector
//Addresses of Vectors. Since Vectors holds a reference to set of values, vectorPointer will hold an address for every set.
void* vectorPointer = malloc(vectorsNumber *sizeof(void*));
//Populating the vectorPointer with the address generated by allocating memory for every set of values
for (int i = 0; i < vectorsNumber; i++)
{
vectorPointer = (int*)malloc(valuesNumber * sizeof(int)); //Values shall be of int types
vectorPointer++; //ILLEGAL since cannot perform arithmetic on pointers of type void. What do do??
}
//Restore the initial address. In any case...ILLEGAL arithmetic. What do do??
for (int i = 0; i < vectorsNumber; i++)
{
vectorPointer--; //Restore the initial address. In any case...ILLEGAL arithmetic.
}
//Declaring the pointer to hold the address of one value. Memory was already allocated before
int* valueAddress;
for (int j = 0; j < vectorsNumber; j++)
{
//Getting the address of the first value of the first Vector
valueAddress = (int*)vectorPointer; //Is this casting valid in C language?
//Populating the value with whatever operation
for (int k = 0; k < valuesNumber; k++)
{
*valueAddress = (k + 1)*(j + 1); //populate the Vector with int values
}
vectorPointer++; //Switch to next Vector.ILLEGAL arithmetic
}
Actually, you only need one pointer. One way of doing it is by allocating enough memory to hold all the values, and then have functions that map the x/y values in the array to the respective memory location. Assume we want those to be the dimensions and our array variable:
int dimX = 10, dimY = 5;
int *array;
You can set a value this way:
void arraySet(int value, int x, int y) {
array[x + dimX * y] = value;
}
And get a value this way:
int arrayGet(int x, int y) {
return array[x + dimX * y];
}
Allocate the memory beforehand such as in the main function:
array = malloc(sizeof(int)*dimX*dimY);
Use it like this:
arraySet(123, 9, 3); // sets the value of [9, 3] to 123
printf("Memory at 9, 3 is %d\n", arrayGet(9, 3));
This "two pointers" idea doesn't make any sense and the code you posted cannot be salvaged. What you should do instead is to use a pointer to a 2D array:
int (*ptr)[x][y] = malloc(sizeof *ptr);
...
free(ptr);
That's it. However, a pointer to a 2D array is cumbersome, since we have to de-reference it before accessing the actual array. That is, we'd end up writing (*ptr)[i][j] = ...; which is ugly.
To dodge this, we can instead still allocate a 2D array, but instead of pointing at "the whole array", we point at the first element, which is a 1D array:
int (*ptr)[y] = malloc( sizeof(int[x][y]) );
...
ptr[i][j] = ... ; // more convenient syntax for access
...
free(ptr);
More info: Correctly allocating multi-dimensional arrays
You can simulate int a[2][3]; with
one dimensional array and index computing:
int* matrix = (int*) malloc(6 * sizeof(int));
int get_matrix_2_3(int* matrix, int i, int j) { return matrix[3 * i + j]; }
2-dimensional array:
int** matrix = (int**) malloc(2 * sizeof(int*));
for (int i = 0; i != 2; ++i) {
matrix[i] = (int*) malloc(3 * sizeof(int));
}
matrix[1][2] = 42;

Removing first X elements from array

I have an array named arr of size 1024. So basically I want to delete the 1st X elements of the array. How would I do that? This is what I am thinking:
Make a pointer pointing to the 1st value of the array (arr[0]). Do pointer arithmetic to take it to the X'th element of the array. Then set the arr[0] to the pointer p, which will effectively remove the first X elements? Will this work?
Or is there an easier way to remove the first X elements of the array?
Since the array is global it will exist in memory until your program terminates. But this won't stop you declaring a pointer which points to one of its internal items, and using this pointer as the start of your array. With your notations: char* p = arr + X; This way p[0] will be equal to arr[X], p[1] to arr[X + 1], and so on.
check out the function memmove, if you can. This is a great way to move a chunk of memory quickly.
If arr is declared as char arr[1024]; then you cannot.
If arr is declared as char * arr = (char *)malloc(1024 * sizeof(char)); then: arr += 3
Or declare it as char do_not_use_this_name[1024]; then use char * arr = do_not_use_this_name + 3;
You can treat arr as a circular buffer. However, you cannot access it like a regular array anymore. You would need an interface.
char arr[1024];
int pos = 0;
int size = 0;
#define arr(i) arr[(pos+(i))%1024]
void append (char v) {
arr(size++) = v;
}
void remove_first_x (int x) {
pos = (pos + x) % 1024;
size -= x;
}
You can move the pointer X units and treat that as the start of the array:
int arr[1024]; // could be other type as well
...
int *p = arr;
...
p += X; // x is the number of units you want to move
Based on your requirement to not use memmove and to cause arr[0] to return the result of arr[x], you could do something like this:
char arr[1024];
int arr_size = sizeof(arr) / sizeof(*arr);
char* source;
char* destination;
char* arr_end = arr + arr_size;
//Initialise the array contents
for (destination = arr, source = arr + x; source < arr_end; ++source, ++destination)
*destination = *source;
Keep in mind that this is just shifting the contents of the array backwards by X. The size of the array is still 1024.
Note that this will not do anything with the remaining X elements at the end of the array. If you want to zero them, you could subsequently do something like this:
for (; destination < arr_end; ++destination)
*destination = 0;

Differences between matrix implementation in C

I created two 2D arrays (matrix) in C in two different ways.
I don't understand the difference between the way they're represented in the memory, and the reason why I can't refer to them in the same way:
scanf("%d", &intMatrix1[i][j]); //can't refer as &intMatrix1[(i * lines)+j])
scanf("%d", &intMatrix2[(i * lines)+j]); //can't refer as &intMatrix2[i][j])
What is the difference between the ways these two arrays are implemented and why do I have to refer to them differently?
How do I refer to an element in each of the arrays in the same way (?????? in my printMatrix function)?
int main()
{
int **intMatrix1;
int *intMatrix2;
int i, j, lines, columns;
lines = 3;
columns = 2;
/************************* intMatrix1 ****************************/
intMatrix1 = (int **)malloc(lines * sizeof(int *));
for (i = 0; i < lines; ++i)
intMatrix1[i] = (int *)malloc(columns * sizeof(int));
for (i = 0; i < lines; ++i)
{
for (j = 0; j < columns; ++j)
{
printf("Type a number for intMatrix1[%d][%d]\t", i, j);
scanf("%d", &intMatrix1[i][j]);
}
}
/************************* intMatrix2 ****************************/
intMatrix2 = (int *)malloc(lines * columns * sizeof(int));
for (i = 0; i < lines; ++i)
{
for (j = 0; j < columns; ++j)
{
printf("Type a number for intMatrix2[%d][%d]\t", i, j);
scanf("%d", &intMatrix2[(i * lines)+j]);
}
}
/************** printing intMatrix1 & intMatrix2 ****************/
printf("intMatrix1:\n\n");
printMatrix(*intMatrix1, lines, columns);
printf("intMatrix2:\n\n");
printMatrix(intMatrix2, lines, columns);
}
/************************* printMatrix ****************************/
void printMatrix(int *ptArray, int h, int w)
{
int i, j;
printf("Printing matrix...\n\n\n");
for (i = 0; i < h; ++i)
for (j = 0; j < w; ++j)
printf("array[%d][%d] ==============> %d\n, i, j, ??????);
}
You are dereferencing the Matrix1 two times..
Matrix1[i][j] ;
It means that it is a 2D array or a double pointer declared like this.
int **Matrix1 ;
A double pointer could be thought of as array of pointers. Its each element is a pointer itself, so it is dereferenced once to reach at the pointer element, and dereferenced twice to access the data member of that member pointer or array. This statement as you you wrote is equivalent to this one..
Matrix1[i][j] ; //is ~ to
*( *(Matrix1 + i) + j) ;
For a single pointer like this.
int *Matrix2 ;
You can derefernce it only once, like this.
Matrix2[i] ; //is ~ to
*(Matrix2 + i) ;
This statement which you wrote..
Matrix2[(i * lines)+j] ;
|-----------|
This portion evaluates to a single number, so it derefenced one time.
(i * lines) + j ;
As for your printmatrix() function, the ptArray passed to it is a single pointer. So you cannot dereference it twice.
Perhaps you can get better understanding of static and dynamic 2D arrays from my answer here.
2D-array as argument to function
Both matrices are sequences of bytes in memory. However, the difference between them is how you're defining the memory interface to represent a matrix. In one case you're just defining a memory segment with a number of elements equal to the elements in the matrix, and in the other case you're specifically allocating memory to represent each specific line.
The following case is more expensive computationally, because you're invoking malloc() a greater number of times:
intMatrix1 = (int **)malloc(lines * sizeof(int *));
for (i = 0; i < lines; ++i)
intMatrix1[i] = (int *)malloc(columns * sizeof(int));
However, it brings the advantage that you get to refer to matrix elements in a clearer fashion:
intMatrix1[i][j];
If you just allocate one sequence of elements equal to the number of elements in the matrix, you have to take in account line/column index calculations to refer to the right matrix elements in memory.
To attempt to increase the degree of uniformity in the code, may I suggest a function that receives the matrix line reference and matrix column-count and prints a line?
void PrintLine(int *ptrLine, int lineLen) {
unsigned int i;
for(i = 0; i < lineLen; i++)
printf("%d ", ptrLine[i]);
printf("\n");
}
And then, for each matrix type, you would just do:
// Case 1
for(i = 0; i < lines; i++)
PrintLine(intMatrix1[i], columns);
// Case 2
for(i = 0; i < lines; i++) {
PrintLine(intMatrix2 + i*columns, columns);
}
In C, the array access operator [] is really just a cleaner way of performing pointer arithmetic. For a one-dimensional array of elements of type type_s, arr[i] is equivalent to *(arr + (i * sizeof(type_s))). To dissect that expression:
arr will be the base address, the lowest memory address where this array is stored
i is the zero-indexed position of the element in the array
sizeof returns the number of chars (which is generally the same as the number of bytes, but it's not mandated by the C spec) that an element in arr takes up in memory. The compiler will determine the size of the element and take care of performing this math for you.
As a side note, this syntax has the side effect of arr[i] being equivalent to i[arr], although it's universally accepted to put the index in brackets.
So with all of that said, let's look at the differences between your two declarations:
intMatrix1[i][j] is equivalent to *(*(intMatrix1 + i * sizeof(int)) + j * sizeof(int)). So, there are two dereference operators in that expression, meaning that intMatrix is an array of arrays (it contains pointers to pointers).
On the other hand, intMatrix2[(i * lines)+j] is equivalent to *(intMatrix2 + ((i * lines) + j) * sizeof(int)), which contains only one dereference operator. What you're doing here is defining a one-dimensional array that contains the same number of elements as the original two-dimensional array. If your data can be best represented by a matrix, then I recommend you use the first version: intMatrix1[i][j].
The difference is that the first array:
intMatrix1 = (int **)malloc(lines * sizeof(int *));
Creates an array of pointers intMatrix1. Each of those pointers points to an int array (which you malloc here).
for (i = 0; i < lines; ++i)
intMatrix1[i] = (int *)malloc(columns * sizeof(int));
That's why you need the 2 stars (dereference to the pointer array, then to the int array) in the declaration and the double brackets to access single elements:
int **intMatrix1;
int i = intMatrix[row][column];
int i = *(*(intmatrix + row) + column);
For the second matrix, you create just an int array of size column * rows.
int *intMatrix2 = (int *)malloc(lines * columns * sizeof(int));
int i = intMatrix[row + column];
int i = *(intMatrix + row + column);
To print the 2 arrays you will have to use different print functions, because the internal structure of the 2 matrix is different, but you already know the different methods to access both arrays.

Resources