passing 2d float array to a function in C++ [duplicate] - c++

I have a 2-dimensional array and I am passing it into a function to carry out certain operations. I'd like to know the correct way of doing it...
#define numRows 3
#define numCols 7
#define TotalNum (numRows*numCols)
int arr[numRows][numCols] = {{0,1,2,3,4,5,6}, {7,8,9,10,11,12,13},{14,15,16,17,18,19,20}};
void display(int **p)
{
printf("\n");
for (int i = 0; i< numRows;i++)
{
for ( int j = 0;j< numCols;j++)
{
printf("%i\t",p[i][j]);
}
printf("\n");
}
}
int main() {
display(arr);
}
I get an error message:
'display': cannot convert parameter1 from 'int' to 'int*'
Is this the correct way of passing a 2-dimensional array into a function? If not, what is the correct way?

You should declare your function like this:
void display(int p[][numCols])
This C FAQ thoroughly explains why. The gist of it is that arrays decay into pointers once, it doesn't happen recursively. An array of arrays decays into a pointer to an array, not into a pointer to a pointer.

If (like in your case), you know the dimensions of the array at compilation-time, you can write justvoid display(int p[][numCols]).
Some explanation: You probably know that when you pass an array to a function, you actually pass a pointer to the first member. In C language, 2D array is just an array of arrays. Because of that, you should pass the function a pointer to the first sub-array in the 2D array. So, the natural way, is to say int (*p)[numCols] (that means p is a pointer, to an array of numCols ints). In function declaration, you have the "shortcut" p[], that means exactly the same thing like (*p) (But tells the reader, that you pass a pointer to a beginning of array, and not to just an one variable)

There are several, sometimes equivalent ways of doing this. By declaring an array (cf. method_c()), by using a pointer (cf. method_b()) or by using a pointer to an array of an array (cf. method_a()). method_b(), using a single pointer, is slightly more difficult to get right since it is not easy to use standard array indexing and hence, we use pointer arithmetic. method_a() and method_c() are basically equivalent since arrays decay non-recursively to pointers during compilation. Here is a little program illustrating all three methods. We first initialize a 2x4-array arr in a simple for loop and print it. It will look like this:
arr:
0 1 2 3
0 1 2 3
Afterwards we call all three methods. method_a() adds 1, method_b() adds 2 and method_c() adds 3 to all elements. After each call we print out the array arr again. If a function worked correctly you will easily see it on the output. Size is arbitrary and can be regulated via the two macros ROW and COL. One last note, method_c() relies on variable-length array present since C99.
#include <stdio.h>
#include <stdlib.h>
#define ROW 2
#define COL 4
void method_a(int m, int n, int (*ptr_arr)[n]);
void method_b(int m, int n, int *ptr_arr);
void method_c(int m, int n, int arr[][n]);
int main(int argc, char *argv[]) {
int arr[ROW][COL];
int i;
int j;
for(i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
arr[i][j] = j;
}
}
printf("Original array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
method_a(ROW, COL, arr);
printf("method_a() array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
printf("method_b() array:\n");
method_b(ROW, COL, (int *)arr);
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
method_c(ROW, COL, arr);
printf("method_c() array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
return EXIT_SUCCESS;
}
void method_a(int m, int n, int (*ptr_arr)[n])
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
ptr_arr[i][j] = j + 1;
}
}
}
void method_b(int m, int n, int *ptr_arr)
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
/* We need to use pointer arithmetic when indexing. */
*((ptr_arr + i * n) + j) = j + 2;
}
}
/* The whole function could have also been defined a bit different by taking
* the i index out of the pointer arithmetic. n alone will then provide our
* correct offset to the right. This may be a bit easier to understand. Our
* for-loop would then look like this:
* for (i = 0; i < m; i++)
* {
* for (j = 0; j < n; j++)
* {
* *((ptr_arr + n) + j) = j + 2;
* }
* ptr_arr++;
* }*/
}
void method_c(int m, int n, int arr[][n])
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
arr[i][j] = j + 3;
}
}
}

You are doing in wrong way. You can pass 2-d array with the help of pointer to an array, or simply pass an array or through Single pointer.
#define numRows 3
#define numCols 7
void display(int (*p)[numcols],int numRows,int numCols)//First method//
void display(int *p,int numRows,int numCols) //Second Method//
void display(int numRows,int numCols,int p[][numCols]) //Third Method
{
printf("\n");
for (int i = 0; i < numRows;i++)
{
for ( int j = 0; j < numCols;j++)
{
printf("%i\t",p[i][j]);
}
printf("\n");
}
}
int main() {
display(arr,numRows,numCols);
}

Declare it simply
void display(int (*p)[numCols][numRows]);
This way your p pointer conveys all necessary informations and you can extract all the dimensions from it without repeating numCols and numRows over and over.
void display(int (*p)[numCols][numRows])
{
size_t i, j;
printf("sizeof array=%zu\n", sizeof *p);
printf("sizeof array[]=%zu\n", sizeof **p);
printf("sizeof array[][]=%zu\n", sizeof ***p);
size_t dim_y = sizeof *p / sizeof **p;
printf("dim_y = %zu\n", dim_y);
size_t dim_x = sizeof **p / sizeof ***p;
printf("dim_x = %zu\n", dim_x);
for(i=0; i<dim_y; i++) {
puts("");
for(j=0; j<dim_x; j++)
printf(" %6d", (*p)[i][j]);
}
}
This is particularly interesting if you use typedefs (which I don't like btw)
typedef int matrix[5][6];
In that case the dimensions are not visible in the signature of the function but the function will still have the correct values for the dimensions.

You can change the signature of display method as follows:
void display(int (*p)[numCols])
Here, p is a pointer to the row of a 2D array. The pointer only needs to know the number of columns in the array.
Actually speaking, pointer need to know the size of each row. This is very important for pointer arithmetic. So that when you increment the pointer, the pointer must point to next row.
Note here, p is not a normal integer pointer. It's a integer pointer to the memory size equal to integer_size x columns.
In main you don't need to change anything. display(arr) is just fine.

Related

Function that accepts a 2D array, multiplies it by an integer, and returns the new 2D array in C++?

say I have a 3x4 array with integer elements, I want to pass this array to a function that then takes all of the elements and multiplies them by some integer 'b' then returns this new array, how would I go about it? this is what I have currently
#include <iostream>
#include <math.h>
using namespace std;
// my function for multiplying arrays by some integer b
int* multarray(int (*a)[4], int b)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
*(*(a+i)+j) *= b;
}
}
return *a;
}
int main()
{
// creating an array to test, values go from 1-12
int arr [3][4];
int k = 1;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
arr[i][j] = k;
k++;
}
}
// trying to setup new 'array' as a product of the test array
int *newarray;
newarray = multarray(arr,3);
// printing values (works with *(newarray+i) only)
for (int i = 0; i < 3; i++)
{
for (int j=0; j<4; j++)
{
cout << *(*(newarray+i)+j);
}
}
return 0;
}
this works if I don't include the j part when printing all my values but as it is now, tells me I have an error: invalid type argument of unary '*' (have 'int')
Your function is not returning a new array, it's modifying an existing array. So (assuming this is not a problem for you) you should just change the return type to void.
void multarray(int (*a)[4], int b)
{
...
}
Then
multarray(arr,3);
for (int i = 0; i < 3; i++)
{
for (int j=0; j<4; j++)
{
cout << *(*(arr+i)+j);
}
}
If you really do want a function that returns a new array, then that's a whole different (and much more complicated) problem . Apart from anything else it's, strictly speaking, impossible to return an array in C++.

C++ 2d static array and memory allocation

I think, I have just made a mistake: I was allocating a static 2D array and accessing it as 1 dimension.
Could you tell me how bad it is - method geta?
The code below works fine on my Windows, and Linux: actual is always eqauls to expected and stride is always equals to N.
#include "stdafx.h"
#define N 2000
int a[N][N];
int geta(int i, int j) {
return *(a[0] + i * N + j);
}
int main()
{
printf("Hello\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
a[i][j] = i + j;
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int const expected = a[i][j];
int const actual = geta(i, j);
if (actual != expected) {
printf("wrong data at [%d,%d] expected=%d actual=%d", i, j, expected, actual);
}
}
}
for (int i = 1; i < N; i++) {
int stride = a[N] - a[N - 1];
if (stride != N) {
printf("wrong: i=%d c=%d N=%d", i, stride, N);
}
}
return 0;
}
Could you tell me how bad it is - method geta?
Bad. But correct. C++ guarantees memory for a to be contiguous and the memory layout to be row major, so your code returns in a correct manner the expected element. Let's see how:
The type of a[0] is int[2000] 1) . But as soon as you do arithmetic on it it decays, i.e. int*. So +i*N moves the pointer to the (beginning of the) line i and +j moves the pointer to the column j.
1) actually it's int(&)[2000] but not that relevant here

Access violation reading from double pointer [duplicate]

I have a 2-dimensional array and I am passing it into a function to carry out certain operations. I'd like to know the correct way of doing it...
#define numRows 3
#define numCols 7
#define TotalNum (numRows*numCols)
int arr[numRows][numCols] = {{0,1,2,3,4,5,6}, {7,8,9,10,11,12,13},{14,15,16,17,18,19,20}};
void display(int **p)
{
printf("\n");
for (int i = 0; i< numRows;i++)
{
for ( int j = 0;j< numCols;j++)
{
printf("%i\t",p[i][j]);
}
printf("\n");
}
}
int main() {
display(arr);
}
I get an error message:
'display': cannot convert parameter1 from 'int' to 'int*'
Is this the correct way of passing a 2-dimensional array into a function? If not, what is the correct way?
You should declare your function like this:
void display(int p[][numCols])
This C FAQ thoroughly explains why. The gist of it is that arrays decay into pointers once, it doesn't happen recursively. An array of arrays decays into a pointer to an array, not into a pointer to a pointer.
If (like in your case), you know the dimensions of the array at compilation-time, you can write justvoid display(int p[][numCols]).
Some explanation: You probably know that when you pass an array to a function, you actually pass a pointer to the first member. In C language, 2D array is just an array of arrays. Because of that, you should pass the function a pointer to the first sub-array in the 2D array. So, the natural way, is to say int (*p)[numCols] (that means p is a pointer, to an array of numCols ints). In function declaration, you have the "shortcut" p[], that means exactly the same thing like (*p) (But tells the reader, that you pass a pointer to a beginning of array, and not to just an one variable)
There are several, sometimes equivalent ways of doing this. By declaring an array (cf. method_c()), by using a pointer (cf. method_b()) or by using a pointer to an array of an array (cf. method_a()). method_b(), using a single pointer, is slightly more difficult to get right since it is not easy to use standard array indexing and hence, we use pointer arithmetic. method_a() and method_c() are basically equivalent since arrays decay non-recursively to pointers during compilation. Here is a little program illustrating all three methods. We first initialize a 2x4-array arr in a simple for loop and print it. It will look like this:
arr:
0 1 2 3
0 1 2 3
Afterwards we call all three methods. method_a() adds 1, method_b() adds 2 and method_c() adds 3 to all elements. After each call we print out the array arr again. If a function worked correctly you will easily see it on the output. Size is arbitrary and can be regulated via the two macros ROW and COL. One last note, method_c() relies on variable-length array present since C99.
#include <stdio.h>
#include <stdlib.h>
#define ROW 2
#define COL 4
void method_a(int m, int n, int (*ptr_arr)[n]);
void method_b(int m, int n, int *ptr_arr);
void method_c(int m, int n, int arr[][n]);
int main(int argc, char *argv[]) {
int arr[ROW][COL];
int i;
int j;
for(i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
arr[i][j] = j;
}
}
printf("Original array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
method_a(ROW, COL, arr);
printf("method_a() array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
printf("method_b() array:\n");
method_b(ROW, COL, (int *)arr);
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
method_c(ROW, COL, arr);
printf("method_c() array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
return EXIT_SUCCESS;
}
void method_a(int m, int n, int (*ptr_arr)[n])
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
ptr_arr[i][j] = j + 1;
}
}
}
void method_b(int m, int n, int *ptr_arr)
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
/* We need to use pointer arithmetic when indexing. */
*((ptr_arr + i * n) + j) = j + 2;
}
}
/* The whole function could have also been defined a bit different by taking
* the i index out of the pointer arithmetic. n alone will then provide our
* correct offset to the right. This may be a bit easier to understand. Our
* for-loop would then look like this:
* for (i = 0; i < m; i++)
* {
* for (j = 0; j < n; j++)
* {
* *((ptr_arr + n) + j) = j + 2;
* }
* ptr_arr++;
* }*/
}
void method_c(int m, int n, int arr[][n])
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
arr[i][j] = j + 3;
}
}
}
You are doing in wrong way. You can pass 2-d array with the help of pointer to an array, or simply pass an array or through Single pointer.
#define numRows 3
#define numCols 7
void display(int (*p)[numcols],int numRows,int numCols)//First method//
void display(int *p,int numRows,int numCols) //Second Method//
void display(int numRows,int numCols,int p[][numCols]) //Third Method
{
printf("\n");
for (int i = 0; i < numRows;i++)
{
for ( int j = 0; j < numCols;j++)
{
printf("%i\t",p[i][j]);
}
printf("\n");
}
}
int main() {
display(arr,numRows,numCols);
}
Declare it simply
void display(int (*p)[numCols][numRows]);
This way your p pointer conveys all necessary informations and you can extract all the dimensions from it without repeating numCols and numRows over and over.
void display(int (*p)[numCols][numRows])
{
size_t i, j;
printf("sizeof array=%zu\n", sizeof *p);
printf("sizeof array[]=%zu\n", sizeof **p);
printf("sizeof array[][]=%zu\n", sizeof ***p);
size_t dim_y = sizeof *p / sizeof **p;
printf("dim_y = %zu\n", dim_y);
size_t dim_x = sizeof **p / sizeof ***p;
printf("dim_x = %zu\n", dim_x);
for(i=0; i<dim_y; i++) {
puts("");
for(j=0; j<dim_x; j++)
printf(" %6d", (*p)[i][j]);
}
}
This is particularly interesting if you use typedefs (which I don't like btw)
typedef int matrix[5][6];
In that case the dimensions are not visible in the signature of the function but the function will still have the correct values for the dimensions.
You can change the signature of display method as follows:
void display(int (*p)[numCols])
Here, p is a pointer to the row of a 2D array. The pointer only needs to know the number of columns in the array.
Actually speaking, pointer need to know the size of each row. This is very important for pointer arithmetic. So that when you increment the pointer, the pointer must point to next row.
Note here, p is not a normal integer pointer. It's a integer pointer to the memory size equal to integer_size x columns.
In main you don't need to change anything. display(arr) is just fine.

Copying a dynamically allocated 2D array

I have a question as follows:
I declared two pointer-to-pointer double-type variables **matrix1 and **matrix2 and allocate them by new operator to become 2D arrays.
First I used for loop to make matrix1 point to double-type data called element, then I copy matrix1 to matrix2, which means matrix2 points to element too. Then problem comes: I used delete operator to terminate matrix1 after copying, but then the values matrix2 point to became extremely strange. I think that was because after deleting matrix1, element terminates, so I think one of a solution is let matrix2 point to other address with the values same with element. But I don't know how to do this(copy element to new dynamic memories and won't disappear after deleting matrix1) in an efficient way, can somebody help me? thank you.
void MatCpy(double **InMat, double **OutMat, int NumOfRow, int NumOfCol)
{
for (int j = 0; j < NumOfRow; j++)
{
for (int i = 0; i < NumOfCol; i++)
{
OutMat[j][i] = InMat[j][i];
}
}
}
double **Malloc2D_Dbl(int row, int col)
{
double **data = new double*[row];
for (int i = 0; i < row; i++)
data[i] = new double[col];
return data;
}
void load(char *load_path, double **data, int height, int width) // function for loading
{
int i = 0, j = 0;
char buffer[30];
file_handle = fopen (load_path, "r");
for (int k = 0; k < width*height; k++)
{
fscanf (file_handle, "%s", &buffer);
j = k / width;
i = k % width;
data[j][i] = atof(buffer);
}
fclose (file_handle);
}
Sorry I am a noob....
More efficient than copying the individual elements is to use memcpy like this:
void MatCpy(double **InMat, double **OutMat, int NumOfRow, int NumOfCol) {
for(int j=0; j<NumOfRow; j++) {
memcpy(OutMat[j], InMat[j], NumOfCol*sizeof(double));
}
}

How to use pointer to pointer for passing matrix?

Passing matrix as a pointer to pointer to function not working.
#include <stdio.h>
void printMatrix(int **matrix, int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
printf("%d ", matrix[i][j]);
printf("\r\n");
}
}
void printM (size_t row, size_t col, int matrix[3][4])
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
printf("%d ", matrix[i][j]);
printf("\r\n");
}
}
int main()
{
int M[3][4];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; j++)
M[i][j] = 4*i+j;
printM(3, 4, M);
int *row = *M;
printMatrix(&row, 3, 4); //not working
}
Function printM works, but I would like to know how to use pointer to pointer correctly, thanks for help.
First of all, thank-you for this question. It is a good review of how C does multi-dimensional arrays. Also, it is OK to do double pointers. Remember an array reference is equivalent to a pointer, such as: a[0] and *a both refer to the first element of int a[12]; where *a is the de-referencing of pointer a. And so, &M is a the address of the pointer M when M is declared as int M[3][4];
I modified your code by adding a few comments for clarity and so that it would run in Eclipse using a C compiler from Microsoft, specifically, int declarations where moved out of the for statements. Other than that it is the same as what you originally wrote with a change to the printMatrix declaration and how it is invoked.
Hope this helps, please ask if more questions...
#include <stdio.h>
void printMatrix(int (*matrix)[3][4], int row, int col)
{
int i, j;
// point t so that when de-referenced it is at
// the matrices first element
int *t = (*matrix)[0];
printf("\n");
for (i = 0; i < row; i++)
{
// in C matrices are stored in Row Major form, so
// per K&R just sequentially loop thru (*t)[12]
for (j = 0; j < col; j++) {printf("%d ", *t++);}
printf("\r\n");
}
} // end printMatrix
void printM (size_t row, size_t col, int matrix[3][4])
{
int i, j;
printf("\n");
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++) {printf("%d ", matrix[i][j]);}
// new line for next row
printf("\r\n");
}
}
int main()
{
int i,j;
// define a matrix with 3 rows and 4 columns
int M[3][4];
// fill-in the matrix with values
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
M[i][j] = 4*i + j;
// print the three rows and four columns of M
printM(3, 4, M);
printMatrix(&M, 3, 4); // Also Works
} // end main
void printMatrix(int *matrix, int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
printf("%d ", *(matrix+(i*col)+j);
printf("\r\n");
}
}
Don't do a double pointer.