Passing multidimensional array by reference in C - c

#include <stdio.h>
void f(int *app[][20]) {
int i, j;
for (i =0; i< 20; i++){
for (j=0; j<20; j++){
*app[i][j] = i;
}
}
}
int main() {
int app[20][20];
int i, j;
f(&app);
for (i =0; i< 20; i++){
for (j=0; j<20; j++){
printf("i %d, j%d val= %d\n", i, j, app[i][j]);
}
}
return 0;
}
What exactly am I doing wrong here? I don't get any error, but there is a segmentation fault and I don't know why.
te.c:15:5: warning: passing argument 1 of ‘f’ from incompatible pointer type
f(&app);
^
te.c:3:6: note: expected ‘int * (*)[20]’ but argument is of type ‘int (*)[20][20]’
void f(int *app[][20]) {

void f(int *app[][20]) { /* a 2d array of pointers to int */
should be
void f(int app[][20]) { /* a pointer to an array of 20 int's */
or
void f(int (*app)[20]) { /* a pointer to an array of 20 int's */
*app[i][j] = i;
should be
app[i][j] = i; /* you don't need to dereference */
f(&app);
should be
f(app);

void f(int *app[][20])
should be
void f(int app[][20])
and the call should be like
f(app);
The changes done in the function f() is visible in main()
You can access the array in function f() like app[i][j]

the following code correctly implements the definition and passing of a pointer to the 'app[][]' array to function 'f'
Notice the replacement of the 'magic' numbers
with #define'd values
Notice the proper use of prototypes.
This will become very important as the projects become larger and consist of multiple files. Although when the project becomes multiple files, then each source file should have its' own header file that contains the prototypes for that source file
The code cleanly compiles and runs correctly
#include <stdio.h>
#define ROWS (20)
#define COLS (20)
void f(int app[][COLS]) ;
int main( void )
{
int app[ROWS][COLS];
int i, j;
f(app);
for (i =0; i< ROWS; i++)
{
for (j=0; j<COLS; j++)
{
printf("i %d, j%d val= %d\n", i, j, app[i][j]);
}
}
return 0;
}
void f(int app[][COLS])
{
int i, j;
for (i =0; i< ROWS; i++)
{
for (j=0; j<COLS; j++)
{
app[i][j] = i;
}
}
}

Related

Function for printing 2D arrays of uknown size in C

I'm new to C programming and I've run into a problem when creating 2D array printing function. When I try to execute the code below I get:
points.c:13: error: unknown array element size
As I've checked there are very similar codes online, which are supposed to work. I've tried to initialize function as
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
but it raises:
points.c:3: error: 'arrayLen' undeclared
Could somebody tell me what's wrong with this code and how to fix it? I also don't understand why very similar function for 1D arrays works just fine. It has to be in pure C.
#include <stdio.h>
//supposed to print 2D array:
int print2DArray(int array[][], int arrayLen, int elementLen)
{
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d", array[i][j]);
}
printf("\n");
}
}
//prints 1D array:
int printArray( int array[], int arrayLen)
{
int i;
for (i = 0; i < arrayLen; i++)
{
printf("%d", array[i]);
}
}
--- edit ---
I undestand most of you pointed out that the function has to be called like that:
#include <stdio.h>
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
{
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d", array[i][j]);
}
printf("\n");
}
}
This raises an error:
points.c:3: error: 'arrayLen' undeclared
I'm using tcc for windows and according to documentation it is supposed to support C99 VLA.
It appears OP's compiler (or the mode it is used) does not support variable length array (VLA) as a function parameter.
Below is a non-VLA approach.
void print2DArrayX(int arrayLen, int elementLen, const int *array) {
int i;
int j;
for (i = 0; i < arrayLen; i++) {
for (j = 0; j < elementLen; j++) {
printf("%5d", array[i*elementLen + j]);
}
printf("\n");
}
}
Call with address of first int, not the 2D array
#define ARRAY_LEN 3
#define ELEMENT_LEN 4
int array[ARRAY_LEN][ELEMENT_LEN] = { 0 };
...
print2DArrayX(ARRAY_LEN, ELEMENT_LEN, array[0]);
Ok, so thanks for all the answers - they were very helpful. I've just tried to use gcc in linux and as you've pointed out this approach works fine:
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
I guess tcc (tiny c compiler, windows version 0.9.27) doesn't support VLA after all. A bit strange since documentation says it does.
How about you try this solution.
#include <stdio.h>
int print2DArray(int* array, int arrayLen, int elementLen)
{
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d ", *(array+j+elementLen*i));
}
printf("\n");
}
}
int main(){
int arr[2][6] = { {9,258,9,96,-8,5},
{1,1212,-3,45,27,-6}
};
print2DArray(*arr,2,6);
return 0;
}
Unless you are using a C99 compiler,
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
is not possible.
Even if you are using C99 compiler, your code has a problem. You need to pass one of the dimension first.
int print2DArray(int arrayLen, int elementLen, int arr[][elementLen]);
So,
int print2DArray(int arrayLen, int elementLen, int arr[][elementLen])
{
// Your code
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d", array[i][j]);
}
printf("\n");
}
return 0;
}
This can be used as
int main(void)
{
int i32Array[3][3] = {{-15, 4, 36}, {45, 55, 12}, {-89, 568, -44568}};
int m = 3, n = 3;
// I am not sure why 'print2DArray' would return an int
// (or anything at all for that matter).
// If you can establish a case for it,
// modify the function and the value it is supposed to return,
// And catch it below.
print2DArray(m, n, i32Array);
return 0;
}
I am not sure how you are calling print2DArray function. Unless you post that piece of code, it is difficult to resolve your problem. Confirm that you are calling the function correctly as shown above.

sorting array with functions without using pointers in C didn't work out. why?

I was trying to sort an array with sending my array to a function but it gives error when compiling. My sorting algorithm might be wrong but that is not a point. I wonder why my compilers give error. Here is my errors :
error: conflicting types for ‘sortarray’
void sortarray(int d[],int size)
note: previous declaration of ‘sortarray’ was here
void sortarray(int,int);
#include<stdio.h>
#define SIZE 9
void sortarray(int,int);
int main()
{
int i;
int c[SIZE]= {2,6,8,10,12,89,68,45,37};
printf("sorting array program: \n");
for (i = 0; i < SIZE; i++)
{
printf("%d ",c[i]);
}
printf("\n");
sortarray(c,SIZE);
for (i = 0; i < SIZE; i++)
{
printf("%d ",c[i]);
}
return 0;
}
void sortarray(int d[],int size){
int hold;
int i,j;
for (i = 0; i < size; i++)
{
for (j = 0; j < size-1; j++)
{
d[j+1]=hold;
d[j+1]=d[j];
d[j]=hold;
}
}
return;
}
The error message is pretty clear.
You declared your function as:
void sortarray(int,int);
But define it as
void sortarray(int d[],int size)
These are not the same, as the type of the first argument are different.
Change the declaration to match the definition:
void sortarray(int [],int);
Change the void sortarray(int,int); to void sortarray(int *,int);, the first parameter is an array.

how do returns a matrix in C (include code)

i defined a matrix into a function. how do i return that matrix for print it when i call it with another function. i mean...
#include<stdio.h>
#include<conio.h>
#include<time.h>
void main() {
int m,n;
printf("type 2 numbers:");
scanf("%i %i",&m,&n);
declaration(m,n);\\HERE IS THE PROBLEM
printing(matrix,m,n);
getch();
}
void declaration(int a,int b) {
srand(time(NULL));
int i,j,matrix[a][b];
for(i=0;i<a;i++){
for(j=0;j<b;j++){
matrix[i][j]=1+rand()%7;
}
}
}
void printing(int c[100][100],int a,int b) {
int i,j;
for(i=0;i<a;i++){
for(j=0;j<b;j++){
printf("%i\t",c[i][j]);
}
printf("\n");
}
}
Define it like:
typedef struct {
int rows;
int cols;
int *data;
} int_matrix_entity, *int_matrix;
int_matrix int_matrix_create(int rows, int cols, bool rand)
{
int_matrix mt;
int i;
if ((mt = malloc(sizeof(int_matrix_entity))) == NULL)
{
return NULL;
}
if ((mt->data = malloc(sizeof(int) * cols * rows)) == NULL)
{
free(mt);
return NULL;
}
if (rand)
{
srand(time(NULL));
for (i = 0; i < cols * rows; i++)
{
mt->data[i] = 1 + rand() % 7;
}
}
else
{
memset(mt->data, 0, sizeof(int) * cols * rows);
}
return mt;
}
void int_matrix_printf(int_matrix mt)
{
int i;
int j;
for (i = 0; i < mt->rows; i++)
{
for (j = 0; j < mt->cols; j++)
{
printf("%5d ", mt[i * cols + j]);
}
printf("\n");
}
}
You have a few points that require a bit more attention;
1 ) read warning and error messages given by your compiler
2 ) again, read warning messages given by your compiler
3 ) use indentation to make your code more readable.
4 ) Always return from main(), that's a good practice
The code below does what you want to achieve; have a look at it and keep on reading...
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
// You either have to declare your functions
// or implement them before main()
void declaration(int a,int b, int m[a][b]);
void printing(int a,int b, int m[a][b]);
int main(){ // always return from main()
int m,n;
printf("type 2 numbers:");
scanf("%i %i",&m,&n);
int matrix[m][n];
declaration(m, n, matrix);
printing(m, n, matrix);
return 0;
}
void declaration(int a,int b, int m[a][b]){
srand(time(NULL));
int i,j;
for(i=0;i<a;i++){
for(j=0;j<b;j++){
m[i][j]=1+rand()%7;
}
}
}
void printing(int a,int b, int m[a][b]){
int i,j;
for(i=0;i<a;i++){
for(j=0;j<b;j++){
printf("%i\t",m[i][j]);
}
printf("\n");
}
}
You need a way to transfer data from one function to another. You cannot simply declare an auto variable in one function and pass it to another as you did in the code below
declaration(m,n);
printing(matrix,m,n); /* where does matrix[][] come from? */
remember, C is a strongly typed language which means you have to declare your variables before using them. This applies to your functions as well. You either have to give your function declarations before main() (or more specifically, before using them), or implement them.
Look into your header files (i.e. .h files) and you will see lots of function declarations.
Since you use variable length arrays, make sure your compiler is at least capable of compiling code confirming C99 standard.
Some extras;
Normally, C passes arguments by value and you have to use a pointer if you want the value of your variable get changed within the function. If you have a close look at the code snippet I gave, I simply used an int m[a][b].In C, the name of an array is a pointer to its first element, hence you can change the value of array elements when actually array's name is passed to your function as an argument.
For further reading, you may want to look at
variable scope
global variables (you can define matrix[][] as a global variable and change the value of matrix elements)
declaration vs definition in C
Another simple way to do it is use double pointer to create 2-dimensional array. Keep it simple.
#include <stdio.h>
#include <stdlib.h>
int** create_matrix(int rows, int cols) {
int **matrix = malloc(rows*(sizeof(int *)));
for(int i = 0; i < rows; i++) {
matrix[i] = malloc(cols*sizeof(int));
}
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
matrix[i][j] = 1 + rand()%7;
}
}
return matrix;
}
void printing(int** matrix, int rows, int cols) {
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(void) {
int rows, cols;
rows = 3, cols = 3;
int** matrix = create_matrix(rows, cols);
printing(matrix, rows, cols);
free(matrix);
return 0;
}

How to pass a contiguous array as a parameter in C?

I have created a contiguous array with random values (0-9), but I don't know how to pass it to a function that would print it.
Right now I'm simply iterating through the array inside the main function, whenever I need to print it. But I want to have a function for that, it would make my code cleaner.
A minimal code example is below:
#include <stdio.h>
#include <stdlib.h>
int **alloc_2d_int(int rows, int cols);
int main(int argc, char** argv){
int **matrix;
int i,j,size=3;
matrix = alloc_2d_int(size,size);
// generate the array
for (i=0; i<size; i++)
{
for (j=0; j<size; j++)
{
matrix[i][j] = rand() % 10;
}
}
// how I print the array right now
for (i=0; i<size; i++)
{
for (j=0; j<size; j++)
{
printf("[%d][%d]=%d\n", i,j,matrix[i][j]);
}
}
// this is how I want the printing to happen
print_arr(matrix,3);
}
int **alloc_2d_int(int rows, int cols) {
int *data = (int *)malloc(rows*cols*sizeof(int));
int **array= (int **)malloc(rows*sizeof(int*));
int i;
for (i=0; i<rows; i++)
array[i] = &(data[cols*i]);
return array;
}
void print_arr(int **array,int size)
{
int i,j;
for (i=0; i<size; i++)
{
for (j=0; j<size; j++)
{
printf("matrix[%d][%d]=%d\n", i,j,array[i][j]);
}
}
}
Error message:
conflicting types for ‘print_arr’ [enabled by default]
You forgot to add the declaration(prototype) of your function. In C language, by-default, the return type of a function is of int type. But for your print_arr() function, the return type is void. So, you get the conflict type error.
So, Declare the print_arr() function above the main() function. Like:
void print_arr(int **array,int size);
You haven't declared print_arr function before the main so it is not able to find it. Rest works smoothly.

Transpose matrix function in C, with function receiving and returning a 2D array

I need to create a function that takes a matrix and returns it transpose. The only requirement is that it directly returns a matrix, not just modifies it by reference. Here's what I've done so far:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define ROW 100000000
#define COL 100000000
int (*(f_MatTrans)(int mat[][COL], int r, int c))[COL];
int main(void)
{
int x[2][2]={1,2,3,4};
int (*a)[2];
a=f_MatTrans(x,2,2);
for(int i=0; i<2; i++)
{
for(int j=0; j<2; j++)
{
printf("X[%d][%d]=%d\n",i,j,x[i][j]);
printf("A[%d][%d]=%d\n",i,j,a[i][j]);
}
}
return 0;
}
int (*(f_MatTrans)(int mat[][COL], int r, int c))[COL]
{
int a[c][r];
for(int i=0; i<r; i++)
{
for(int j=0; j<c; j++)
{
a[j][i]=mat[i][j];
}
}
return a;
}
The purpose of this is to include the function on a library created by myself, just in case it is useful information.
The code in the question (when I read it) doesn't compile because the array x is not compatible with the function signature.
I'm not clear what the real constraints on your problem are. The easy way to do it in C99 or C11 is with VLA notation:
#include <stdio.h>
static void MatrixTranspose(int r, int c, int src[r][c], int dst[c][r])
{
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
dst[j][i] = src[i][j];
}
int main(void)
{
int x[3][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
int y[2][3];
MatrixTranspose(3, 2, x, y);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
printf("X[%d][%d]=%d ", i, j, x[i][j]);
printf("Y[%d][%d]=%d\n", j, i, y[j][i]);
}
}
return 0;
}
Sample output:
X[0][0]=0 Y[0][0]=0
X[0][1]=1 Y[1][0]=1
X[1][0]=2 Y[0][1]=2
X[1][1]=3 Y[1][1]=3
X[2][0]=4 Y[0][2]=4
X[2][1]=5 Y[1][2]=5
My suspicion is that you are supposed to be doing something different (notationally more complex), but it is not yet clear what.
You cannot return a pointer to the local array, because that ceases to exist when the function returns. If you want your function to create the result array (not write to some other array that is passed into the function), you must use malloc() in these cases:
//The return type is actually `int (*)[r]`, but C doesn't like that.
int* f_MatTrans(int r, int c, int mat[][c]) {
int (*a)[r] = malloc(c*sizeof(*a));
for(int i=0; i<r; i++) {
for(int j=0; j<c; j++) {
a[j][i]=mat[i][j];
}
}
return *a;
}
Note that I changed the array types: If you declare mat as int mat[][COL], the number COL will be used to calculate the offset mat[1][0], which will be 100000000 integers after the first element in your case, while the array that you pass in only contains four integers. This is undefined behavior, and your program is allowed to format your harddrive if you do this.
Unfortunately, it is not possible for the type of the returned pointer to depend on the value of an argument to the function. That is why I changed the return type to a plain integer pointer, you must document that this is meant to be a pointer of type int (*)[r].
You would use the function above like this:
int main(void) {
int x[2][3]={1,2,3,4,5,6};
int (*a)[2] = (int (*)[2])f_MatTrans(2, 3, x);
for(int i=0; i<2; i++) {
for(int j=0; j<2; j++) {
printf("X[%d][%d]=%d\n",i,j,x[i][j]);
printf("A[%d][%d]=%d\n",i,j,a[i][j]);
}
}
free(a); //Cleanup!
return 0;
}

Resources