Passing two-dimensional array via pointer - c

How do I pass the m matrix to foo()? if I am not allowed to change the code or the prototype of foo()?
void foo(float **pm)
{
int i,j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
printf("%f\n", pm[i][j]);
}
int main ()
{
float m[4][4];
int i,j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
m[i][j] = i+j;
foo(???m???);
}

If you insist on the above declaration of foo, i.e.
void foo(float **pm)
and on using a built-in 2D array, i.e.
float m[4][4];
then the only way to make your foo work with m is to create an extra "row index" array and pass it instead of m
...
float *m_rows[4] = { m[0], m[1], m[2], m[3] };
foo(m_rows);
There no way to pass m to foo directly. It is impossible. The parameter type float ** is hopelessly incompatible with the argument type float [4][4].
Also, since C99 the above can be expressed in a more compact fashion as
foo((float *[]) { m[0], m[1], m[2], m[3] });
P.S. If you look carefully, you'll that this is basically the same thing as what Carl Norum suggested in his answer. Except that Carl is malloc-ing the array memory, which is not absolutely necessary.

If you can't change foo(), you will need to change m. Declare it as float **m, and allocate the memory appropriately. Then call foo(). Something like:
float **m = malloc(4 * sizeof(float *));
int i, j;
for (i = 0; i < 4; i++)
{
m[i] = malloc(4 * sizeof(float));
for (j = 0; j < 4; j++)
{
m[i][j] = i + j;
}
}
Don't forget to free() afterwards!

You can't. m is not compatible with the argument to foo. You'd have to use a temporary array of pointers.
int main()
{
float m[4][4];
int i,j;
float *p[4];
p[0] = m[0];
p[1] = m[1];
p[2] = m[2];
p[3] = m[3];
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
m[i][j] = i+j;
foo(p);

If you have a compiler that supports C99, the current C standard, then you can do this:
foo((float *[]){ m[0], m[1], m[2], m[3] });
(Note that this is exactly the same as AndreyT's answer, except that it forgoes having to name the temporary array)

you dont need to do any changes in the main,but you function will work properly if you change the formal prototype of your function to (*pm)[4] or pm[][4] because **pm means pointer to pointer of integer while (*pm)[4] or pm[][4] means pointer to poiner of 4 integers .
m here is also a pointer to pointer of 4 integers and not pointer to pointer of integers and hence not compatible.
#include<stdio.h>
void foo(float (*pm)[4])
{
int i,j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
printf("%f\n", pm[i][j]);
}
int main ()
{
float m[4][4];
int i,j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
m[i][j] = i+j;
foo(m);
}

Does foo(m) not work?

void foo(float **pm) is the same as void foo(float *pm[]) which is not a two-dimensional array of floats. It is an array of float*. Now, those float* may themselves point to float arrays, but that's a separate matter.

typedef float Float4[4];
void foo(Float4 *pm)
{
int i,j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
printf("%f\n", pm[i][j]);
}
main()
{
Float4 m[4];
int i,j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
m[i][j] = i+j;
foo(m);
return 0;
}

Using C99 which supports run-time sized arrays, the following is a possible way to pass a 2-dim array:
void foo(void *pm, int row, int col)
{
float (*m)[col] = pm;
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
printf("%4.1f%s", m[i][j], (j == col-1)?"\n":" ");
}
int main()
{
float m[4][4];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
m[i][j] = i+j;
foo(m, 4, 4);
return 0;
}

Related

Double pointer addresses

I created and allocated a double pointer like this:
int **a;
a = (int**)malloc(10 * sizeof(int *));
for (int i = 0; i < 10; i++)
*(a+i) = (int *)malloc(10 * sizeof(int));
And then I initialized it for example like this:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
**a = 1;
(*a)++;
}
a++;
}
My problem and question is how can I save the address'es of my double pointer?At this moment I lost them and can't use them anymore.
Don't use explicit pointer arithmetic and dereferencing when array subscripting will do:
int rows = 10, cols = 10
int **a;
// don't cast the return value of malloc
a = malloc(rows * sizeof(*a));
for (int i = 0; i < rows; i++)
a[i] = malloc(cols * sizeof(**a));
...
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
a[i][j] = 1;
}
}
Return a from a function, save it as a class member, it is just like any other variable. If you want to save the contents of the arrays then do that (but that is not what I could call saving a double pointer -- by the way the usual description is "pointer-to-pointer").

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!

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?).

C: Matrix multiplication using double pointers

I've been given a code that reads in the matrix from two text files. (Assuming that is correct) I need to come up with a function that multiples two matrices together.
This is the given function prototype:
int** matMult(int **a, int num_rows_a, int num_cols_a, int** b, int num_rows_b, int num_cols_b);
And here is my code for the function:
int** matMult(int **a, int num_rows_a, int num_cols_a, int** b, int num_rows_b, int num_cols_b){
int **c;
c = (int**)malloc(sizeof(int*)*num_rows_a);
// c = calloc(num_rows_a, num_cols_b);
for (int i = 0; i < num_rows_a; i++) {
for (int j = 0; j < num_cols_b; j++) {
int sum = 0;
for (int k = 0; k < num_cols_a; k++) {
c[i][j] = a[i][k] * b[k][j] + sum;
sum = c[i][j]; //so that previous answer gets stored
}
}
}
return c;
}
I have to call malloc to allocate space for the resulting matrix, c
Also the issue I'm getting from Xcode is : EXC_BAD_ACCESS
You need to allocate memory for columns too. :
int **c;
c = (int**)malloc(sizeof(int*)*num_rows_a);
for(i=0;i<num_rows_a;i++)
c[i]=malloc(sizeof(int)*num_cols_b);
The answer by #Stinson addresses the memory problem already. I'm going to suggest a little refinement of the inner block of code. There is no need to have temporary sum in the code.
for (int i = 0; i < num_rows_a; i++) {
c[i] = malloc(sizeof(int)*num_cols_b);
for (int j = 0; j < num_cols_b; j++) {
// Initialize the element to zero.
c[i][j] = 0;
for (int k = 0; k < num_cols_a; k++) {
// Accumulate the result
c[i][j] += a[i][k] * b[k][j];
}
}
}

array of pointers to bit arrays

I want to make an array of pointers to bit arrays. I make this func2 to test the pointers, but I get a seg fault when I try to acess an elemeny of the bit array outside the function. What am I doing wrong?
int func2(int i, int* bit_array){
int j;
for(j = 0; j< i; j++)
bit_array[j] = malloc(sizeof(int) * i);
for(j = 0; j< i; j++)
bit_array[j] = 0;
return 1;
}
int main(){
int** bit_root;
bit_root = malloc(sizeof(int *) * 5);
func2(5, bit_root);
int n;
for(n = 0; n < 5; n++)
printf("%d ", bit_root[0][n]); //error
printf("\n");
return 0;
}
You are sending the array incorrect to the function func2. func2 need to be:
int func2(int i, int** bit_array){
int j,k;
for(j = 0; j< i; j++)
bit_array[j] = malloc(sizeof(int) * i);
for(j = 0; j< i; j++)
for(k = 0; k< i; k++)
bit_array[j][k] = 0;
return 1;
}
int main(){
int** bit_root;
bit_root = malloc(sizeof(int *) * 5);
func2(5, bit_root);
int n;
for(n = 0; n < 5; n++)
printf("%d ", bit_root[0][n]); //error
printf("\n");
return 0;
}
In the lines below you allocate memory for array of int for each element of bit_array and assign pointers to int arrays to bit_array elements:
for(j = 0; j< i; j++)
bit_array[j] = malloc(sizeof(int) * i);
But here you assign zeroes to bit_array elements. Thus you rewrite pointers to zero as if you didn't allocate memore at all:
for(j = 0; j< i; j++)
bit_array[j] = 0;
To fix it replace the this last block this a following code:
int k;
for(j = 0; j< i; j++)
for(k = 0; k < i; k++)
bit_array[j][k] = 0;
Here in the first loop you iterate through the array of pointers to int arrays (bit_array[j]) and in the inner loop you iterate through the array of ints (bit_array[j][k]). These changes requires changing of func2 definition - second parameter must be pointer to pointer to int instead of just a pointer. It helps you to get rid from warnings of compiler.
To see what is going on clearly you can use following code:
int k, *int_array = NULL;
for(j = 0; j< i; j++)
{
int_array = bit_array[j]; // get the pointer to int array
for(k = 0; k < i; k++)
int_array[k] = 0; // assign values to int array
}
And don't forget to free all these memory for both inner arrays and bit_array.

Resources