Passing a two dimensional array to a function in C - c

#include <iostream>
#include <math.h>
#include <stdio.h>
#define column 3
#define row 3
#define share 3
int matrix_multiplication(int left_matrix[][column], int right_matrix[][column], int result_matrix[][column], int rows, int cols, int shared);
int A[][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
},
B[][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}, C[3][3]; //initialize "hard coded" three matrices
int main() {
matrix_multiplication(A, B, C, row, column, share); //passes address of each matrix to function
return 0;
}
int matrix_multiplication(int left_matrix[][column], int right_matrix[][column], int result_matrix[][column], int rows, int cols, int shared) {
int i, j, k;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {//stays within first column and row through first iteration
for (k = 0; k < 3; k++)//ensures inner dimensions match with variable k i.e. ixk * kxj =ixj or A*B=C
result_matrix[i][j] += right_matrix[i][k] * left_matrix[k][j]; //C programming has ability to perform matrix multiplication
//Adds result of each operation to C matrix i.e. +=
printf("%d\t", result_matrix[i][j]); //matrix C is composed of rows(i) and columns(j)
}//new tab after each column iteration
printf("\n"); //new line for each row iteration
}
return 0;
}
This code is an good example of passing multidimensional arrays to a function using pointers and printing multidimensional arrays after mutliplication. There are multiple ways to indicate pointers to the compiler. I recommend seeing the "Correct way of passing a 2 dimensional array into a function." for example:
/*void display(int (*p)[numcols],int numRows,int numCols)//First method//
void dispaly(int *p,int numRows,int numCols) //Second Method//
void dispaly (int p[][numCols],int numRows,int numCols) //Third Method*/

Remove the column variable, and add this above the matrix_multiplication function declaration:
#define column 3
(You may also want to rename column to COLUMNS.)
In C++ you can also do this:
static const int column = 3;
or, in C++11:
constexpr int column = 3;
The idea behind all this is that all but the very first size of a multidimensional array must be known at compile time.
To fix the expected primary-expression before ']' token" error, change your inner assignment to something like this:
result_matrix[i][j] += right_matrix[i][k] * left_matrix[k][j];
Also you should initialize result_matrix with 0s first.
Also remove the * from int *result_matrix[][column].
Most modern compilers display warnings if you pass an int instead of an int*. Please enable all warnings in your compiler, recompile, fix them, and update your question stating that the example code compiles cleanly, without warnings.
To print an element of the matrix, you have to specify which element you want to print:
printf("%d\t", result_matrix[i][j]);
I can't believe that your compiler didn't display a warning when you omitted the [i][j]. Warnings are for your benefit: they indicate possible bugs in your code.

Related

What is the C syntax/operator for adding matrixes?

I am relatively new to C programming and am stuck with a problem. I am trying to create a 'Transpose function' that will take a matrix_a and transpose and store it as matrix_b. The end goal is to call this function in an equation later on.
For example: Result_Matrix = Matrix_A + Transpose_Matrix_A + Matrix B*MatrixA
Ideally I would just call the Transpose function in the equation, not sure if that is even possible in C but that's my thought process.
This is what I have got so far
#include <stdio.h>
#define N 4
// This function stores transpose of A[][] in B[][]
void transpose(int A[][N], int B[][N])
{
int i, j;
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
B[i][j] = A[j][i];
}
int main()
// Specify matrix
{
int A[N][N] = { {1, 1, 1, 1},
{2, 2, 2, 2},
{3, 3, 3, 3},
{4, 4, 4, 4}};
int B[N][N], i, j;
transpose(A, B);
// printf("Result matrix is \n");
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
printf("%d ", B[i][j]);
printf("\n");
}
return 0;
}
This transposes a matrix but it does not store the new matrix.
Edit 1: I know the transpose function works but I am not sure how to call it in an equation:
New_Matrix = Matrix_A + Transpose_Function(Matrix_A)
^I want to call the function I created in an equation like so.
As kaylum explained, C does not offer the kind of operator use which you are imagining.
Even if your functions would return something (most likely a pointer to the result matrix), adding it with + would not be what you need.
So it is necessary to call functions, e.g. as kaylum proposed:
transpose(A, B); matrix_add(A, B, C); with final result in C
After the call to transpose() the transposed matrix is found in B, which has to be a suitably sized array (be careful with your code and non-square matrixes by the way). Then, without an operator like + being used, that B is used as parameter to a function matrix_add(), which does not exist in your shown code, but structurally is similar to the one you created. Again, C contains the final result and must be a suitably sized array with scope and life-time beyond that second function (like the B you created).

How can I use int** to pass a 2D array in C

Trying to work on leetcode #497 in C on my vscode. When writing main(), I am not sure how to deal with int** that leetcode provides. Is it possible to pass a 2D array using int**?
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int rectsSize;
int * rectsColSize;
int** rects;
} Solution;
int points[100];
Solution* solutionCreate(int** rects, int rectsSize, int* rectsColSize) {
Solution* sol = malloc(sizeof(Solution));
sol->rects = rects;
sol->rectsSize = rectsSize;
sol->rectsColSize = rectsColSize;
//some codes
}
return sol;
}
int* solutionPick(Solution* obj, int* retSize) {
//some codes
return ret;
}
void solutionFree(Solution* obj) {
free(obj);
}
int main(void)
{
int rects[2][4] = {{1, 1, 5, 5}, {6, 6, 9, 9}};
int rectsSize = 2;
int rectsColSize = 4;
int retSize;
Solution* obj = solutionCreate(rects, rectsSize, &rectsColSize);
int* param_1 = malloc(sizeof(int));
param_1 = solutionPick(obj, &retSize);
solutionFree(obj);
return 0;
}
While in general there are many different ways to handle 2D array, the simple answer is no. There is a lot of info about 2d arrays in C: 1, 2, 3, etc. In principle, when dealing with 2d arrays, every dimension except first to the left needs to be specified exactly. In your case, every rectangle is defined by 4 integers, so instead int** rects consider int*[4] rects. This makes rectsColSize useless, because now each column has constant size of 4 ints.
Just for completness: what you are trying to do is second approach to arrays, where each column has independent size, and (usually) additional malloc call. While this approach is also valid and requires int** type, it is not needed for your task. Nice description of the difference here.
Edit
Here is how to loop through 2d arrays:
#define col 4
void print_2d(int (*a)[col], int aSize){
for(size_t i = 0; i < aSize; i++){
for(size_t j = 0; j < col; j++){
printf("%d ", a[i][j]);
}
printf("\n");
}
}
and here for int**:
void print_pp(int** a, int aSize, int* aiSize){
for(size_t i = 0; i < aSize; i++){
for(size_t j = 0; j < aiSize[i]; j++){
printf("%d ", a[i][j]);
}
printf("\n");
}
}
It seems that you want to convert int*[4] to int**, or more precisely, int*[4] arr2d with it's size int arr2dSize to structure Solution. In that case, here is wrapper to solutionCreate.
Solution* solutionCreateWrap(int (*arr2d)[4], int arr2dSize) {
int* rectsColSize = malloc(arr2dSize * sizeof(int));
int** rects = malloc(arr2dSize * sizeof(int*));
size_t arr2dMem = arr2dSize * 4 * sizeof(int);
rects[0] = malloc(arr2dMem);
memcpy(rects[0], arr2d, arr2dMem);
rectsColSize[0] = 4;
for(size_t i = 1; i < arr2dSize; i++){
rects[i] = rects[0] + i*4;
rectsColSize[i] = 4;
}
sol->rects = rects;
sol->rectsSize = rectsSize;
sol->rectsColSize = rectsColSize;
//some codes
}
return solutionCreate(rects, arr2dSize, rectsColSize);
}
Now for int rects[2][4] = {{1, 1, 5, 5}, {6, 6, 9, 9}}; call solutionCreateWrap(rects, 2) will return initialised structure Solution. It looks gruesome, and it's details are even worse, so if it just works, you may skip the explanation. Understanding low level C details isn't neccesarily to write in it, and this (or any other) explanation cannot possibly cover this matter, so don't be discouraged, if you won't get it all.
arr2d is contiguous block of memory of arr2dSize*4 integers. When multiplied by sizeof(int) we get size in bytes - arr2dMem in my code. Declaration int (*arr2d)[4] means, that arr2d is of type int*[4]. Knowing this we can cast it to int* like so: int* arr = (int*)arr2d and expression arr2d[i][j] is translated as arr[i*4+j].
The translation to rects is as follows; int** is array of pointers, so every rect[i] has to be pointer to i-th row of arr2d. Knowing this, everything else is pointer arithmetic. rects[0] = malloc(arr2dMem); and memcpy(rects[0], arr2d, arr2dMem); copies whole arr2d to rect[0], then every next rects[i] = rects[0] + i*4; is shifted 4 integers forward. Because rect is of type int**, the expression rects[i][j] translates to *(rects[i]+j), and replacing rects[i] by rects[0] + i*4, we get *((rects[0] + 4*i)+j), that is rects[0][4*i+j]. Note striking similarity between last expression, and arr[i*4+j]. rectsColSize is somewhat superfluous in this case, but it is essential in general int** array, when every subarray could have different sizes. After wrap function is done, rects is exact copy of arr2d, but with type appropriate for your Solution structure, so we can call solutionCreate().

How to pass unbound multidimensional array?

Is there any way to pass a multidimensional array to a function without knowing the no of columns.... I mean say I want to print a multidimensional array say a[][9] and b[][3]. If I make a common function say print.
// I have to specify the no of columns right and since
// the no of columns should be same for both actual and
// formal arguments
void print(int a[][])
I have to make different functions for different multidimensional arrays. There should be some way around it.
How to pass unbound multidimensional array?
You have to include all of the array dimensions, except the innermost one (although you probably do want to give the innermost one anyway, so that your function knows when to stop printing). If the dimension is not known at compile time then you can make it a parameter to the function:
void print(size_t m, size_t n, int a[m][n])
{
for ( size_t i = 0; i < m; ++i )
for ( size_t j = 0; j < n; ++j )
printf("%d\n", a[i][j]);
}
Calling the function:
int main(void)
{
int a[][4] = { { 0, 1, 2, 3 }, {8, 7, 6, 5}, {11, 10, 12, 9} };
print(3, 4, a);
return 0;
}
Matt McNabb's answer shows how to use the C99 or C11 variable-length array facilities. There is an alternative that will work with C89 too (which might be a factor if you code on Windows with MSVC), but you still have to tell the function about both dimensions of the array, and you have to do the subscript calculations yourself:
void print(size_t m, size_t n, int *a)
{
size_t i;
size_t j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
printf(" %d", a[i * n + j]);
putchar('\n');
}
}
You might call this as:
int main(void)
{
int a[][4] = { { 0, 1, 2, 3 }, {8, 7, 6, 5}, {11, 10, 12, 9} };
print(3, 4, &a[0][0]);
return 0;
}
Sample output:
0 1 2 3
8 7 6 5
11 10 12 9
(One minor comment: I'm not certain that the automatic array could be initialized like that in C89 — there were some restrictions still on automatic variable initialization. If it doesn't work, simply move the entire array declaration outside of main() and prefix it with static so it becomes a file scope array.)

Getting garbage value while passing an entire array to a function

I'm trying to pass an entire array to the function but the last value i get is always a garbage value and not 3. Please point out where I've made a mistake.
#include<stdio.h>
#include<conio.h>
main() {
int array[3] = {0, 1, 2, 3};
display(&array[0], 3);
}
display(int *j, int n) {
int i;
for(i=0; i<=n; i++) {
printf("\n%d", *j);
j++;
}
}
You have an off-by-one error in your for loop. Your array has only three elements. You try to read four elements instead of three.
Change your code to this (note the < instead of <=):
for (i = 0; i < n; i++) {
You also try to initialize the array with four elements when it only has room for three:
int array[3] = {0, 1, 2, 3};
Maybe you can try to change your compiler settings to flag this as a warning/error. Then you might get something like this that would notify you of the problem:
prog.c: In function ‘main’:
prog.c:13: error: excess elements in array initializer
prog.c:13: error: (near initialization for ‘array’)
The array variable represent an address of first element so no need to use & address operator with the function call and another issue is with size of an array.
main() {
int array[4] = {0, 1, 2, 3};
display(array, 3);
}
display(int *j, int n) {
int i;
for(i=0; i<=n; i++) {
printf("\n%d", *j);
j++;
}
}
There a few observations in the code:
1. main() should be int main(void) or int main(int argc, char **argv). Also you need to return an int value from main when to change it to int main(void) or int main(int argc, char **argv)
2. You are initializing an array of 3 elements with 4 values.
Either declare as int array[3] = {0, 1, 2}; or as int array[] = {0, 1, 2, 3}; (this will create an array with 4 elements)
3. display(int *j, int n) should have a return type say void display(int *j, int n) (otherwise it default to int in which case the function is not returning any value). In this case you will have to define the function before using.
4. In current case, to the function display you are passing an array of 3 elements and accessing element at index 3 (when i equals n) in the for loop which is the 4th element (i.e. out of bounds which is undefined behavior). Remember that array in C is zero indexed. So for(i=0; i<=n; i++) should be for(i=0; i<n; i++)
Hope this helps!
You cannot pass "an entire array to a function" -- C does not do this. Instead, you are passing a pointer to the first element of the array.
main() {
int array[3] = {0, 1, 2, 3};
main should be declared int main(int argc, char* argv[]). It's not that horrible to type, and you can even get your text editor to do it for you, if you care enough.
You have declared array to contain only three items, but store four items into the array. This should have thrown a compile warning at the least. Pay attention to those warnings. Don't specify the size of your array unless that size is vital (Say, if you wanted to keep track of US states, then int states[50] = { ... }; might make sense. For now. Maybe this is a bad example.)
for(i=0; i<=n; i++) {
printf("\n%d", *j);
j++;
for(i=0; i<=n; i++) is very often a bug -- C array indexes run from 0 to n-1, not 0 to n. You're reading one-past-the-array, and that value is not surprisingly garbage.
Further this code is awkward; you should just use printf("\n%d", j[i]) and not increment j each time. Incrementing two variables as "loop variables" this way is a recipe for writing bugs in the future. (If you need to update two variables with every loop iteration, place both in the last section of the for(;;i++, j++) loop.)
Your array is declared to have 3 elements yet you initialize it with 4:
int array[3] = {0, 1, 2, 3};
You create an array for only 3 integers, but put 4 in it. But the error is when you print the array, you print four entries, though only three exist.

Reference a 2-D array column in C?

Is there an easy way to reference a column in a 2-D array as a separate 1-D array in plain old C (not C++ or C#)? It's easy to do this for a row. Asssume I have 2 functions:
double doSomethingWithARow( double theRow[3] );
double doSomethingWithACol( double theCol[100] );
Then, I might use the first one like this:
double matrix[100][3];
double result;
// pass a single row to a function as an array
// this essentially passes the 3-element array at row 48 to the function
for( int i=0; i < 100; i++ )
{
result = doSomethingWithARow( matrix[i] );
}
What I want it a way to access a column easily.
for( int j=0; j < 3; j++ )
{
result = doSomethingWithACol( ??????????? );
}
The only thing I've come up with so far is transforming the matrix to swap the rows with the columns. But this code is supposed to be as efficient as possible in terms of memory and speed. With all of the convoluted ways to reference pointers in C, it seems like there should be a way to do this.
Well, you'd have to pass the size of a row, and the number of rows:
double doSomethingWithACol(double *matrix, size_t colID, size_t rowSize, size_t nRows);
Now you can make use of the fact that matrix[i][j] = matrix + i * rowSize + j;
Alternatively, you can also use the following signature:
double doSomethingWithACol(double *colPtr, size_t rowSize, size_t nRows);
Here, you'll have to pass the pointer to the first element of the column that you want to process, instead of the pointer to the first row.
Example code: This code sums the elements in the second column (compile with gcc -o main -Wall -Wextra -pedantic -std=c99 test.c):
#include <stdio.h>
#include <stdlib.h>
double colSum1(double *matrix, size_t colID, size_t rowSize, size_t nRows)
{
double *c = NULL, *end = matrix + colID + (nRows * rowSize);
double sum = 0;
for (c = matrix + colID; c < end; c += rowSize) {
sum += *c;
}
return sum;
}
double colSum2(double *colPtr, size_t rowSize, size_t nRows)
{
double *end = colPtr + (nRows * rowSize);
double sum = 0;
for (; colPtr < end; colPtr += rowSize) {
sum += *colPtr;
}
return sum;
}
int
main(void)
{
double matrix[4][3] = {
{0, 1, 2},
{3, 4, 5},
{6, 7, 8},
{9, 10, 11}
};
printf("%f\n", colSum1(*matrix, 1, 3, 4));
printf("%f\n", colSum2(&matrix[0][1], 3, 4));
printf("%f\n", colSum2(matrix[0] + 1, 3, 4));
return EXIT_SUCCESS;
}
A nice typesafe way to do this without specifying the dimensions as a separate parameters is as follows:
#define ROWS 100
#define COLUMNS 30
void doSomethingToAllRows(double (*row)[ROWS][COLUMNS], int col, double val)
{
for(size_t i = 0; i < ROWS; ++i)
(*row)[i][col] = val;
}
void doSomethingToAllColumns(double (*col)[ROWS][COLUMNS], int row, double val)
{
for(size_t i = 0; i < COLUMNS; ++i)
(*col)[row][i] = val;
}
int main(int argc, char **argv)
{
double matrix[ROWS][COLUMNS];
/* Modify each column of the 10th row with the value of 3 */
doSomethingToAllColumns(&matrix, 10, 3);
/* Modify each row of the 10th column with the value of 3 */
doSomethingToAllRows(&matrix, 10, 3);
return 0;
}
It is completely wrong to pass a double ** for this reason:
void test()
{
double **a;
int i1 = sizeof(a[0]);//i1 == 4 == sizeof(double*)
double matrix[ROWS][COLUMNS];
int i2 = sizeof(matrix[0]);//i2 == 240 == COLUMNS * sizeof(double)
}
If you passed in a double ** then accessed it like an array you would cause a crash, segfault or undefined behavior.
Since the "columns" as you call them are stored discontiguously in memory, there's no real way to pull this off directly.
You can, however, create an array of pointers, and store references to the indexes of the other array in that one. You'd need to loop through all of the elements in your array, so it's probably not a better solution than any other. Depending on how often you need to access the array by column it might be worthwhile, though.
You can't really do that, because arrays in C are stored such that the elements of each row are stored together. That means a row of an array is a continuous block of memory, and as far as C is concerned it might as well be an independent array itself. It doesn't work the same way with columns because the elements of a column are not continuous in memory; rather they are spaced at intervals of N bytes, where each row is N bytes long. This means that you could efficiently access the various elements of a column of a 2D array by using pointer arithmetic, but there's no way to actually make a column into an array itself other than by copying the elements over into a new array.
No, there isn't. There cannot be, since in C, an array is a consecutive part of memory, and it is trivial that rows and columns cannot be consecutive at the same time.
That being said, it is fairly easy to jump from one cell of a column to the next, if you know the length of the rows. Take the following example:
void processColumn(double *array, int colIdx, int rowLen, int rowCnt) {
for (int i = colIdx; i < rowCnt * rowLen; i += rowLen) {
// do whatever you want
}
}
#define N 5
#define M 10
double array[N*M];
processColumn(array, 3, N, M);

Resources