Printing contents of matrix by using pointer - c

Here is my assignment:
arrPrintMatrix(int *matrix, int m, int n): prints the content of the
matrix[m][n] to the screen in table format.
And here is my code:
#include <stdio.h>
#include <malloc.h>
int main() {
void arrPrintMatrix(int *matrix, int m, int n);
int matrix[2][3] = {{5, 10 , 15}, {0, 2, 4}};
int *ptr;
ptr = &matrix[0][0];
arrPrintMatrix(ptr, 2, 3);
return 0;
}
void arrPrintMatrix(int *matrix, int m, int n) {
int i, j;
for (i = 0; i < m; i++) {
printf("\n");
for (j = 0; j < n; j++) {
printf("%d\t", matrix[i] + j);
}
}
}
But when I run this code, I get 5 6 and 7 as first row, 10 11 and 12 as second row. So something wrong with matrix[i] + j. How should I fix this?
By the way, I'm so confused about arrays of pointers, malloc, pointers to functions, so generally I'm confused about pointers. I would be glad if you suggest some web pages or videos about that.

Change the line
printf("%d\t", matrix[i] + j);
to
printf("%d\t", matrix[i*n+j]);
Update
Layout of memory of 2D arrays is nicely explained in this article.

mChange:
matrix[i] + j
To:
matrix[(i*n)+j]

Related

Printing a 2-D array in a function in C

I want to initialise and print a 2-D array in two separate functions, but i don't really know if i am doing this correctly.
I wrote 2 functions: int** matrix_initialization(int n, int m) and int print_matrix(int n1, int n2, int **a);
In the first function i have to arguments: int n - the number of rows and int m - the number of cols. In this function i initialise a pointer to the pointer int **matrix = NULL; Then i allocate memory to it, and giving this 2-D array random values.
Is that okay that the type of the int** matrix_initialization(int n, int m) function is int ** ?
The second function is int print_matrix(int n1, int n2, int** a) and there are some problems, the main is that it is not working. I have three arguments int n1 - rows, int n2 - cols, int** a a pointer to the pointer. This function is to print matrix.
Here is my code:
#include <stdio.h>
#include <locale.h>
#include <stdlib.h>
#include <time.h>
int** matrix_initialization(int n, int m)
{
int** matrix = NULL;
matrix = (int**)malloc(n * sizeof(n));
if (matrix != NULL)
{
if (matrix != NULL)
{
for (int i = 0; i < m; i++)
{
*(matrix + i) = (int*)malloc(m * sizeof(m));
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = rand() % 20 - 5;
}
}
}
}
return matrix;
}
int print_matrix(int n1, int n2, int** a)
{
for (int i = 0; i < n1; i++)
{
for (int j = 0; j < n2; j++)
{
printf("%d\t", a[i][j]);
}
printf("\n");
}
}
int main()
{
srand(time(NULL));
int N, M, **a;
scanf_s("%d %d", &N, &M);
a = matrix_initialization(N, M);
print_matrix(N, M, a);
}
There are many issues with this code.
Major:
You aren't using 2D arrays but arrays of pointers. That doesn't make the slightest sense for this application, you are just making your code more complex, error prone and slow for absolutely nothing gained. See Correctly allocating multi-dimensional arrays.
matrix = (int**)malloc(n * sizeof(n)); Both of your malloc calls are strange, n is just a size parameter (could as well be size_t) and not necessarily of the same type as the data. Which is a int* in this case, not an int. You should be allocating something like matrix = malloc(n * sizeof(*matrix))
The first for loop for (int i = 0; i < m; i++) is wrong, should be n.
You aren't freeing allocated memory.
Minor:
locale.h isn't needed for this program.
There's no actual need to initialize your pointer matrix to NULL if you are to assign to it on the next line. Also you have multiple redundant checks vs NULL.
*(matrix + i) is never the best way to access an array in C, it's just an obscure way of writing matrix[i]. Don't complicate things just for the heck of it.
Don't name parameters n and m in one function and then n1 n2 in another function. Don't complicate things just for the heck of it.
Avoid functions ending with _s unless you have specific reasons why you need to use them. They are non-portable. It's very likely that whoever told you to use it has no idea what they are talking about. Including no idea about the whole "bounds-checking interface" debacle in C11.
int main() is obsolete style, always use int main (void) (as opposed to C++).
Here is a rewrite with all problems fixed, using 2D arrays instead:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void* matrix_initialization (int n, int m)
{
int (*matrix)[m] = malloc( sizeof(int[n][m]) );
if (matrix != NULL)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = rand() % 20 - 5;
}
}
}
return matrix;
}
void print_matrix (int n, int m, int a[n][m])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d\t", a[i][j]);
}
printf("\n");
}
}
int main (void)
{
srand(time(NULL));
int N, M;
scanf("%d %d", &N, &M);
int (*a)[M];
a = matrix_initialization(N, M);
print_matrix(N, M, a);
free(a);
}
You have two major problems:
The first is
malloc(n * sizeof(n))
which is the same as
malloc(n * sizeof(int))
And that makes no sense when you want to create an array of n pointers to int. On a 64-bit system it's unlikely that sizeof(int) == sizeof(int *).
It should be
malloc(n * sizeof(int*))
Or better yet
malloc(n * sizeof *matrix)
The second problem is your loop where you allocate the int arrays:
for (int i = 0; i < m; i++)
You have just created an array of n elements. Now you iterate over m elements? This will only work if n == m.
The correct loop should of course be
// Iterating over an array of n elements
for (int i = 0; i < n; i++)
You also have the same problem with the malloc call as mentioned above, but this time it just so happens to work because m is an int which is the right type and size.
On another few notes, in C you should not cast the result of malloc.
You never free any of the data you allocate, leading to memory leaks.
And instead of *(matrix + i) use matrix[i].
#include <stdio.h>
#include <locale.h>
#include <stdlib.h>
#include <time.h>
int** matrix_initialization(int n, int m)
{
int** matrix = NULL;
//matrix = (int**)malloc(n * sizeof(n));
matrix = (int**)malloc(n * sizeof(int *));
if (matrix != NULL)
{
for (int i = 0; i < n; i++)//here is n,not m
{
matrix[i] = (int*)malloc(m * sizeof(int));
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = rand() % 20 - 5;
}
}
}
return matrix;
}
int print_matrix(int n1, int n2, int** a)
{
for (int i = 0; i < n1; i++)
{
for (int j = 0; j < n2; j++)
{
printf("%d\t", a[i][j]);
}
printf("\n");
}
return 0;
}
int main()
{
srand(time(NULL));
int N, M, **a,i;
scanf("%d %d", &N, &M);
a = matrix_initialization(N, M);
print_matrix(N, M, a);
//free all the memory
for (i = 0; i<N; i++) {
free(a[i]);
}
free(a);
return 0;
}

passing 2d array in c using pointer to pointer by typecasting

How to pass a 2D array as a parameter in C?
I was searching to pass a 2d array to a function in c and I came across the above site. I understood the first and second way of passing 2d array, but I got
confused in the 3rd method, specifically, how is it even working that way?`
3) Using an array of pointers or double pointer
In this method also, we must typecast the 2D array when passing to function.
#include <stdio.h>
// Same as "void print(int **arr, int m, int n)"
void print(int *arr[], int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
}
int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3;
int n = 3;
print((int **)arr, m, n);
return 0;
}
Output:
1 2 3 4 5 6 7 8 9
`
The above code works fine on codeblocks.
When calling print() from main(), we pass arr as argument by typecasting it to pointer to pointer , but in the function print() it dereferences only once to print the values. printf("%d ", *((arr+i*n) + j));
Shouldn't it be *((*arr+i*n) + j));, I tried compiling this statement , it compiles but doesn't execute.
2) Using a single pointer
In this method, we must typecast the 2D array when passing to function.
#include <stdio.h>
void print(int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
}
int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;
print((int *)arr, m, n);
return 0;
}
Output:
1 2 3 4 5 6 7 8 9
`
The 2nd method and the 3rd method only differ in the type of argument passed in the print() function while rest of the code is same. So what is actually the difference between the working of the functions?
easiest way to pass 2D array,
function
void PrintArray(unsigned char mat[][4]){
int i, j;
printf("\n");
for(i = 0;i<4;i++){
for(j = 0;j<4;j++)
printf("%3x",mat[i][j]);
printf("\n");
}
printf("\n");
}
main
int main(){
int i,j;
//static int c=175;
unsigned char state[4][4], key[4][4], expandedKey[176];
printf("enter the value to be decrypted");
for(i=0;i<4;i++)
for(j=0;j<4;j++)
scanf("%x",(unsigned int *)&state[j][i]);
PrintArray(state);
return 0;
}

When passing 2d array to function what is the difference between single pointer and double pointer?

We can pass a 2d array as a single pointer and as well as a double pointer. But in the 2nd case the output is not as expected. So what is wrong in the 2nd code?
Method 1:
#include <stdio.h>
void print(int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
}
int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;
print((int *)arr, m, n);
return 0;
}
Output:
1 2 3 4 5 6 7 8 9
Method 2:
#include <stdio.h>
void print(int *arr[], int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
}
int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3;
int n = 3;
print((int **)arr, m, n);
return 0;
}
Output:
1 3 5 7 9 3 0 -1990071075 0
The first one is undefined behavior: Accesing a 2D array using a single pointer.
The second one is simply wrong, you can't pass a 2D array (arr[][3]) to an array of int pointers (*arr[]), take a look to Correct way of passing 2 dimensional array into a function:
void print(int *arr[], int m, int n)
Must be
void print(int arr[][3], int n) /* You don't need the last dimesion */
or
void print(int (*arr)[3], int n) /* A pointer to an array of integers */
But this way the column in arr[][3] must be globally defined. Isn't
any other workaround?
Under C99 you can use VLA's (Variable-length array):
void print(int rows, int cols, int arr[rows][cols])
Alter Mann is right, but the main problem in Method 2 is this code:
*((arr+i*n) + j)
Since arr is now type of int *arr[], the element size is sizeof(int *) and not sizeof(int) as in the first case. So when f.e. arr = 0, then arr + 1 equals to 0 + sizeof(int*) instead of 0 + sizeof(int) as in the first case. It would work okay if the arr was casted to (int*) like:
*(((int *)arr+i*n) + j)
TL;DR you're jumping through the array by the pointer size, not an integer size.
My personal suggestion is to use pointers, but access it like an array:
int *arr[];
return arr[i][j];
This works every time unlike the pointer arithmetic that might bite you with the step size, like it did with your case.

why we must typecast the 2D array when passing to function using single pointer?

Hi i was trying to pass 2d array of integer using single pointer.I came to know that i must
typecast array before passing to the function
Can anyone please explain why we need to typecast before pass my code is below?
#include <stdio.h>
void print(int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
}
int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;
print((int *)arr, m, n); // here why i need to typecast and pass?
return 0;
}
Because arr without the cast decays into int (*)[3] (pointer to a block of 3 ints) and your function is expecting int * (pointer to 1 int)..
Since there is no conversion between int (*)[3] and int*, you must employ a cast to force it.
Just pass a 2D array to your function :
void print(int a[][3], int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", a[i][j]);
}
Generally, typecasting will change the properties of a variable. In main function, arr is a 2D array but print function treats arr as a pointer.So typecasting is required
Example for property change:
In main function, if you increment the arr + 1 12 bytes will get incremented, but in case of print function arr + 1 will increment only 4 bytes.

Printing 2D Array using pointers in C

#include "stdio.h"
void main(){
int a[2][2]={1, 2, 3, 4};
int a[2][2]={1, 2, 3, 4};
display(a, 2, 2);
show(a, 2, 2);}
}
display(int *k, int r, int c){
int i, j, *z;
for(i = 0; i < r; i++){
z = k + i;
printf("Display\n");
for(j = 0; j < c; j++){
printf("%d", *(z + j));
}
}
}
show(int *q, int ro, int co){
int i, j;
for(i = 0; i < ro; i++){
printf("\n");
for(j = 0; j < co; j++){
printf("%d", *(q + i*co + j));
}
}
}
Output:
Display
12
23
Show
12
34
Why Display() is not showing 1223 while show() gives 1234? Both uses the same logic to display the 2d array. Can any one help please?
In display you are using two counters, i for rows and j for columns. Since the array is laid out sequentially in memory you need to increase i by the size of a column, i.e. c, each time you want to move from one row to the next. So, you should add i*c to k, not i.
The complete function:
display(int *k,int r,int c){
int i,j,*z;
for(i=0;i<r;i++){
z=k+i*c;
printf("Display\n");
for(j=0;j<c;j++){
printf("%d",*(z+j));
}
}
}
To access 2D array using pointers:
#define R 2
#define C 2
...
int A[R][C]={1, 2, 3, 4};
for(i=0;i<R;i++)
for(j=0;j<C;j++)
printf("%d ",*(*(A+i)+j));
...

Resources