Trouble passing a 2d array to function after malloc - c

I've gotten back into C recently after a long absence, and I can't for the life of me remember how to pass a 2D matrix to a function and use it after mallocating it. I believe I've passed the pointer correctly, but I can't seem to actually access anything in the matrix and can't figure out why.
This is what I have written:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
void matrixOperation(int *arr, int m, int n)
{
printf("in matrixOperation\n ");
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d\n", *((arr+i*n) + j));
}
int main()
{
int i,j,count;
int row, col;
//------------------------------
printf("Number of rows?\n ");
scanf("%d", &row);
printf("Number of columns?\n ");
scanf("%d", &col);
//------------------------------
int* arr[row];
for (i = 0; i < row; i++)
arr[i] = (int*)malloc(col * sizeof(int));
count = 0;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
arr[i][j] = ++count;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf("%d\n",arr[i][j]);
// We can also use "print(&arr[0][0], m, n);"
matrixOperation((int *)arr, row, col);
for (int i = 0; i < row; i++)
free(arr[i]);
return 0;
}
The goal was to have it accept user input for the size of the matrix, fill each index with a count and then pass it to a function which would print it out. However when I try it the print statement just outputs random numbers which I assume are what the pointers are pointing at.
I would like matrixOperation to print out the same thing as the print statement in main and I can't quite figure out what I've done wrong.

Change the function signature and you should be able to use the same piece of code.
void matrixOperation(int **arr, int m, int n)
{
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d\n",arr[i][j]);
}
Call with:
matrixOperation(arr, row, col);
Remember when an array is passed to a function, it "decays" into a pointer. You have an array of pointers. That decays to a pointer to pointers.

You declared an array of pointers:
int* arr[row];
So pass this array to the function.
The function will be declared like:
void matrixOperation(int **arr, int m, int n)
{
printf("in matrixOperation\n ");
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d\n", *( *( arr + i ) + j ) );
}
and call the function like:
matrixOperation( arr, row, col );
Though it will be better to define the function like:
void matrixOperation(int **arr, int m, int n)
{
printf("in matrixOperation\n ");
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < n; j++ )
{
printf("%d ", *( *( arr + i ) + j ) );
}
putchar( '\n' );
}
}
Pay attention to that this expression with the pointer arithmetic:
*( *( arr + i ) + j )
can be rewritten using the subscript operator the following way:
arr[i][j]
The both expressions are equivalent each other.
As for your call of the function with casting the array designator:
matrixOperation((int *)arr, row, col);
then it is wrong because you do not have one extent of memory. You allocated several extents of memory.

Related

Matrix Multiplication Using double pointers passing into functions in C

I am wondering why I cannot get the value in the function, it always cause segmentation fault...
`
void multiply(int M, int N, int K, int **matrixA, int **matrixB, int **matrixC){
for (int i = 0; i < M; i++){
for (int j = 0; j < K; j++){
int sum = 0;
for (int k = 0; k < N; k++){
sum += (*(*(matrixA + j) + k)) * (*(*(matrixB + k) + j));
}
*(*(matrixC + i) + j) = sum;
}
}
}
int main(){
int M, N, K;
scanf("%d%d%d", &M, &N, &K);
int matrixA[M][N];
int matrixB[N][K];
int matrixC[M][K];
for(int i=0; i<M; i++){
for(int j=0; j<N; j++){
scanf("%d", matrixA[i]+j);
}
}
for(int i=0; i<N; i++){
for(int j=0; j<K; j++){
scanf("%d", matrixB[i]+j);
}
}
multiply(M, N, K, (int **)matrixA, (int **)matrixB, (int **)matrixC);
for(int i=0; i<M; i++){
for(int j=0; j<K; j++){
printf("%d ", matrixC[i][j]);
}
printf("\n");
}
return 0;
}
`
I want to print out the result "matrixC", but in the function, it would cause segmentation fault. I have tried several times, and it seems like it would miss the addresses of the pointer under the double pointers.
Change the prototype of the function multiply to this:
void multiply(int M, int N, int K, int matrixA[M][N], int matrixB[N][K], int matrixC[M][K]);
make your life easier like this (body of function multiply):
for (int i = 0; i < M; i++) { //for each row of matrixA
for (int j = 0; j < K; j++) { //for each column of matrixB
matrixC[i][j] = 0; //set field to zero
for (int k = 0; k < N; k++) { //for each col of A and each row of B
//take the dot product of row i (matrixA) and col j (matrixB)
matrixC[i][j] += matrixA[i][k] * matrixB[k][j];
}
}
}
You have an error in this line
sum += (*(*(matrixA + j) + k)) * (*(*(matrixB + k) + j));
which has been corrected to
matrixA[i][k] //index 'i' not 'j'
The var sum is not needed, therefore opted out.
Based on your comment below
Consider the following code:
int arr[2][2];
int n=0;
for (int i=0; i < 2; ++i) {
for (int j=0; j < 2; ++j) {
arr[i][j] = ++n;
printf("%p (%d) ", &arr[i][j], arr[i][j]);
}
printf("\n");
}
Possible output:
0x7fff7c729470 (1) 0x7fff7c729474 (2)
0x7fff7c729478 (3) 0x7fff7c72947c (4)
As you can see, nicely packed into consecutive integers (basically one array of ints - but that is not guaranteed).
Now have a look at this:
int **parr = (int**) arr;
for (int i=0; i < 2; ++i) {
for (int j=0; j < 2; ++j) {
printf("%p ", *(parr + i) + j);
}
printf("\n");
}
Possible output:
0x200000001 0x200000005
0x400000003 0x400000007
Now, that looks (dangerously) ugly.
As always: pointer != array. Pointer to pointer means, an address of another address, whereas an array is a consecutive block of a type (you could for example take the address of the first element, which is done if the array decays to a pointer).
You have to give the compiler enough information, e.g.
int (*parr)[2] = arr;
See also: https://en.cppreference.com/w/c/language/array#Multidimensional_arrays

counting negative integers in a matrix

i am having error while running this code
negativenoinmatrix.c:10:16: error: subscripted value is neither array nor pointer nor vector
if(z[i][j]<0)
i want to calculate the number of negative integers in a matrix
#include <stdio.h>
int negnumbers(int *z, int n, int m)
{
int count = 0;
int i = 0;
int j = m - 1;
while (j >= 0 && i < n)
{
if (z[i][j] < 0)
{
count += (j + 1);
i += 1;
}
else
j -= -1;
}
return count;
}
int main()
{
int n = 3, m = 4;
int a[n][m];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
scanf("%d", &a[i][j]);
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
printf("%d ", a[i][j]);
printf("\n");
}
int val = negnumbers((int *) a, 3, 4);
printf("%d", val);
}
The function needs to accept a pointer to an array, not a pointer to a single item. Change it to
int negnumbers(int n, int m, int z[n][m])
...
int val = negnumbers(3, 4, a);
(Where int z[n][m], as per the rule of "array adjustment", will get changed by the compiler internally to a pointer to the first element, int (*z)[m].)
When you pass a 2-d array to a function, at least the 2nd dimension must be specified. Change to this:
int negnumbers(int z[][4],int n,int m)
You can then use this more straightforward approach to counting the negative numbers:
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (z[i][j] < 0)
count++;
}
}
You are calling a pointer z, and also creating a dynamic matrix out of it. So you need to allocate some memory for it which can be done with:
malloc(z[i][j])
Then after you're done, make sure you deallocate the memory now or else you'll have a memory leak, which you can read more about at Memory Leaks wikipedia.
This is done by calling free(...)
Hope this solves the not an array or pointer error!

While Performing 2D array representation in memory leads to Segmentation fault: 11

I've presented the codes below only while executing the first loop it works fine but as soon as i uncomment the second loop it starts to throw segmentation fault. My code is as below.
// Write a program to add two m*n matrices using pointer.
#include <stdio.h>
#define m 2
#define n 2
int main() {
int (*a)[n];
int (*b)[n], i, j; //, *(sum)[n], i, j;
printf("Enter first matrix:\n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
scanf("%d", *(a + i) + j);
}
}
printf("Enter second matrix:\n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
scanf("%d", *(b + i) + j);
}
}
// printf("The Sum of matrix is:\n");
// for (i = 0; i < m; i++) {
// for (j = 0; j < n; j++) {
// // *(*(sum + i) + j) = *(*(a + i) + j) + *(*(b + i) + j);
// // printf("\t%d", *(*(sum + i) + j));
// }
// printf("\n");
// }
}
You are not defining a and b as 2D arrays, but as uninitialized pointers to 2D arrays. passing addresses into these invokes undefined behavior. You must make these pointers point to an actual array, either static, automatic or allocated from the heap.
You can define 2D arrays this way:
int a[m][n], b[m][n];
If you are required to use pointers, you can allocate the 2D arrays with malloc:
int (*a)[n] = malloc(sizeof(*a) * m);
int (*b)[n] = malloc(sizeof(*b) * m);
In your program, it is more readable to use the [] syntax, even for pointers:
#include <stdio.h>
#include <stdlib.h>
#define m 2
#define n 2
int main(void) {
int (*a)[n] = malloc(sizeof(*a) * m);
int (*b)[n] = malloc(sizeof(*b) * m);
int (*sum)[n] = malloc(sizeof(*sum) * m);
printf("Enter first matrix:\n");
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &a[i][j]);
}
}
printf("Enter second matrix:\n");
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &b[i][j]);
}
}
printf("The Sum of matrices is:\n");
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
sum[i][j] = a[i][j] + b[i][j];
printf("\t%d", sum[i][j]);
}
printf("\n");
}
return 0;
}

Output the values of a matrix by passing its pointer to a function

I am trying to send a pointer of a matrix to function for printing the values. However, my following code prints some long numbers so I assumed it prints the addresses instead! How can I print the value of the matrix after passing the pointer of it?
#include <stdio.h>
#include <string.h>
#include <math.h>
void printing(int *edge);
void main(){
int N=3;
int i,j;
int *edge[N];
for (i = 0; i < N; i++){
*(edge+i) = (int *)malloc(N * sizeof(int));
}
srand(0);
for(i = 0; i < N; i++){
for(j = 0; j < N; j++){
if(i == j)
*(*(edge+i)+j) = 0;
else
*(*(edge+i)+j) = 1; //rand() % 10;
}
}
printing(edge); // Pass the pointer of the matrix
}
void printing(int *edge){
int i,j;
int N= 3;
for( i = 0; i < N; i++){
for(j = 0; j < N; j++){
printf("%d \t", ((edge+i)+j)); // I think I have to do something in this line.
}
printf("\n");
}
}
The parameter type of printing is incorrect. It should be int *edge[]. Then when you print, use *(*(edge+i)+j), or better yet edge[i][j].
The result:
void printing(int *edge[]){
int i,j;
int N = 3;
for( i = 0; i < N; i++){
for(j = 0; j < N; j++){
printf("%d \t", edge[i][j]);
}
printf("\n");
}
}
Also, be sure to #include <stdlib.h>, as it's needed for malloc and srand.

C - How to adapt this code for a very large/dynamic array to a 2 dimensional array?

int main()
{
double *array;
long int n;
n=10000000;//10^7
array = (double *) malloc(n*sizeof(double));
return 0;
}
basically, I want to use this code for a really big aray into a 2 dimensional array, which will have dimensions [very large][4].
If you want a 2D array, then allocate a 2D array. It's that simple.
double (*pArr)[4] = malloc(10000000 * sizeof pArr[0]);
Notes:
do not cast the return value of malloc().
use sizeof pArr[0] instead of sizeof(TheDataType) for defensive programming reasons.
This seems working on Wandbox.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
double (* array)[4];
long int n;
int i, j;
n=10000000;//10^7
array = (double (*)[4]) malloc(n*sizeof(double[4]));
printf("%u\n",(unsigned int)sizeof(array[0]));
printf("%u\n",(unsigned int)sizeof(double[4]));
for (i = 0; i <n; i++) {
for (j = 0; j < 4; j++) array[i][j] = (double)i * j;
}
for (i = 0; i < 10; i++) {
for (j = 0; j < 4; j++) printf("%f ", array[i][j]);
putchar('\n');
}
for (i = n - 10; i < n; i++) {
for (j = 0; j < 4; j++) printf("%f ", array[i][j]);
putchar('\n');
}
free(array);
return 0;
}
int n = 100000;
double** array = malloc(sizeof(double*)*n);
for (int i = 0; i < n; ++i)
{
array[i] = malloc(4*sizeof(double));
}
Also note that we don't cast the malloc's result(Do I cast the result of malloc?).

Resources