I have a problem with a c code i am writing. It has to multiply 2 matrix (filled with randoms integers between 0-9) of a given dimension (mxn multiplied by nxm and the result being an mxm matrix). The matrix are filled by columns. Also i have to output the computing times for both the whole program and the execution of the function that does the calculation.
I am getting an "glibc detected" error while executing the application. I do know that it is due to heap corruption in my program, most likely due to having written outside memory on the malloc'ed arrays by I am unable the find where the error is.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define A(i,j) aa[m*(j)+(i)] //matrix by columns
#define B(i,j) bb[n*(j)+(i)]
#define C(i,j) cc[m*(j)+(i)]
void mmul (int m, int n, double *aa, double *bb, double *cc) {
int i, j, k;
for (i=0; i<m; i++)
for (j=0; j<m; j++) {
C(i,j)=0;
for (k=0; k<n; k++) C(i,j)+=A(i,k)*B(k,j);
}
}
int main (int argc, char *argv[]) {
clock_t exec_timer=clock(), comp_timer;
srand(time(NULL)); //initialize random seed
int m, n, i;
double *aa, *bb, *cc, exec_time, comp_time;
if (argc!=3
|| sscanf(argv[1], "%d", &m)!=1
|| sscanf(argv[2], "%d", &n)!=1
) {
fprintf(stderr, "%s m n \n", argv[0]);
return -1;
}
/* malloc memory */
aa=malloc(m*n*sizeof(int)); //integer matrix
bb=malloc(n*m*sizeof(int));
cc=malloc(m*m*sizeof(int));
/* fill matrix */
for (i=0; i<m*n; i++) aa[i]=rand()%10; //fill with random integers 0-9
for (i=0; i<n*m; i++) bb[i]=rand()%10;
/* compute product */
comp_timer=clock();
mmul(m,n,aa,bb,cc);
comp_time=(double) (clock() - comp_timer) / CLOCKS_PER_SEC;
/* write output */
for (i=0; i<m*m; i++) printf("%i\n",cc[i]);
/* finishing */
free(aa); free(bb); free(cc);
exec_time=(double) (clock() - exec_timer) / CLOCKS_PER_SEC;
printf("exec time = %.3f, comp = %.3f\n", exec_time, comp_time);
return 0;
}
#undef C
#undef B
#undef A
Anyone can see the problem I am missing?
Well, yes, I can see the problem.
You are working with arrays of double, but your allocation code uses int. Since typically a double is twice the size of an int, this leads to horrible amounts of buffer overflow, trashing random memory.
Basically, this:
aa=malloc(m*n*sizeof(int)); //integer matrix
is lying. :) It should be:
aa = malloc(m * n * sizeof *aa); /* Not an integer matrix! aa is double *. */
And the same for the allocations of bb and cc, of course.
Note use of sizeof *aa (meaning "the size of the value pointed at by the pointer aa") to remove the risk of introducing this error, i.e. by not repeating the type manually but instead "locking" it to an actual pointer, you make the code safer.
As a minor note, not related to the problem, you should use const for the read-only arguments to mmul(), like so:
void mmul (int m, int n, const double *aa, const double *bb, double *cc)
That immediately makes it obvious which pointer(s) are inputs, and which is output. It can also help the compiler generate better code, but the main advantage is that it communicates much more clearly what you mean.
Related
In my function bodies reduce() and initialize(...) I want to work with the array globalArray as a three-dimensional one, where the dimensions are not known until runtime.
How do I cast the globalArray pointer to a variable-length array (pointer) and use it naturally?
I think the typedef approach helps, but I'm still lost. This current version compiles and seemingly works after my tinkering. Are Cast #1 and Cast #2 as clear and safe as can be achieved?
#include <stdlib.h>
#include <stdio.h>
double * globalArray; /* working from a situation where the array is global, declared elsewhere */
int M, N, P; /*array dimensions not known until runtime */
double reduce();
double reduce()
{
/* Here I want to re-interpret the one-dimensional globalArray into
a multi-dimensional variable-length array so that compiler takes
care of the indexing math for me.*/
typedef double (*arr_t)[N][P];
const arr_t castArray = (arr_t)globalArray; /* Cast #1 */
double sum=0.0;
for (int i=0; i<M; i++)
for (int j=0; j<N; j++)
for (int k=0; k<P; k++)
sum += castArray[i][j][k];
return sum;
}
void initialize(int M, int N, int P, double threedimarray[M][N][P])
{
for (int i=0; i<M; i++)
for (int j=0; j<N; j++)
for (int k=0; k<P; k++)
threedimarray[i][j][k] = (double)(i*N*P + j*P + k);
}
int main(int argc, char **argv)
{
M = 10; N=1000; P=200;
globalArray = malloc( M*N*P* sizeof(double) );
typedef double (*arr_t)[N][P];
initialize(M, N, P, (arr_t)globalArray); /* Cast #2 */
double result = reduce();
printf("Reduced result: %f\n", result );
return 0;
}
https://ideone.com/5Y8Q64
I'm reworking a small section of a large program. There are clearly better design approaches than program scope array pointers. It is what it is.
From a self-documenting point-of-view, it'd be nice if the solution doesn't throw away the fact that we "know" the extent of the leading dimension (M) as well.
The similar SO questions relating to function argument declarations are helpful but I'm not connecting the dots I guess. I decided to ask here hoping the answer will reach more people.
Here's one possible casting solution I've arrived at after some tinkering.
typedef double (*arr_t)[N][P];
arr_t castArray = (arr_t)globalArray;
/* Now castArray can be accessed by multi-dimensional index notation */
castArray[i][j][k] = 3.14;
Downsides:
1) Does not self-document known leading dimension length M.
So I have a program in C structured in 3 files: main.c, alloc.h and alloc.c. In the main.c function, I have the declaration of a pointer to another pointer to which I intend to alloc an n * m array:
#include <stdio.h>
#include <stdlib.h>
#include "alloc.h"
int main() {
int **mat, n, m;
alloc_matrix(&mat, int &n, int &m);
return 0;
}
In alloc.c I have the following declarations:
#ifndef ALLOC_H_INCLUDED
#define ALLOC_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
void alloc_matrix(int***, int*, int*);
#endif
In alloc.c I have the function:
void alloc_matrix(int ***mat, int *n, int *m) {
printf("\nn = "); scanf("%d", n);
printf("\nm = "); scanf("%d", m);
*mat = (int**)calloc(*n, sizeof(int*));
int i;
for (i = 0; i < *n; i++)
*(mat + i) = (int*)calloc(*m, sizeof(int));
}
But the program doesn't work. It enters some kind of loop and doesn't end.
If I allocate it in main it would work but I have no idea what I am doing wrong in the alloc function.
Here is the correct code. Your error was that in the definition of alloc_matrix, you used *(mat+i) in the allocation loop, which should be *(*mat+i) as, mat is a int*** so the base address for the 2D array would be in *mat. Then you need to move by offset i and then de-reference that memory location for the 1D array.
Main:
#include <stdio.h>
#include <stdlib.h>
#include "alloc.h"
int main()
{
int **mat,n,m;
alloc_matrix(&mat,&n,&m);
return 0;
}
alloc.h
#ifndef ALLOC_H_INCLUDED
#define ALLOC_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
void alloc_matrix(int***,int*,int*);
#endif
alloc.c :
void alloc_matrix(int ***mat,int *n,int *m)
{
printf("\nn = "); scanf("%d", n);
printf("\nm = "); scanf("%d", m);
*mat = (int**)calloc(*n,sizeof(int*));
int i;
for(i = 0; i < *n; i++)
*(*mat+i) = (int*)calloc(*m,sizeof(int));
}
The code for the read function :
void read_matrix(int ***mat,int n,int m)
{
int i,j;
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
{
printf("mat[%d][%d] = ", i, j);
scanf("%d", (*(*mat+i))+j);
}
}
The problem with it is that it only reads the first row and the it freezes.
void alloc_matrix(int ***mat,int *n,int *m)
There are two problems in this line. Neither is fatal but both are worth fixing.
First problem: A matrix in this program is represented as an int**. Why does alloc_matrix accept an int***? All standard functions that allocate something (malloc and friends) return a pointer to that something. This is an idiomatic way of doing things in C. It reduces your star count (being a three-star C programmer is not an achievement to be proud of) and simplifies the code. The function should be changed to
int** alloc_matrix( // but what's inside the () ?
The second problem is, why should a function called alloc_matrix prompt the user and read values? These things are not related to allocation. A function should do one thing and do it well. Does malloc prompts you to enter the size? Does fopen prompt you to enter the filename? These things would be regarded as nonsense of the first degree, and rightly so. It is advised to read the sizes elsewhere and pass them to alloc_matrix as input arguments. Hence,
int** alloc_matrix(int n, int m) { // but what's inside the {}?
What remains of alloc_matrix is simple:
int** alloc_matrix(int n, int m) {
int** mat; // that's what we will return
int i;
mat = (int**)calloc(n, sizeof(int*));
for(i = 0; i < n; i++)
// here comes the important part.
Since we have simplified alloc_matrixand reduced the star count in mat, what should we do with the old body of the loop? It was:
*(mat+i) = (int*)calloc(...);
but if we remove a star, it becomes
(mat+i) = (int*)calloc(...);
which is an obvious nonsense. Perhaps the old line was a problem. The fact that it provoked a compiler warning certainly doesn't speak for its correctness. So how to correct it? There aren't too many options. It turns out that in order to restore sanity, we must leave the old left-hand side (written for the three-star mat) intact. Or, better still, use an equivalent but more idiomatic notation:
mat[i] = (int*)calloc(m, sizeof(int));
So the entire function now becomes
int** alloc_matrix(int n, int m) {
int **mat;
int i;
mat = (int**)calloc(n, sizeof(int*));
for(i = 0; i < n; i++)
mat[i] = (int*)calloc(m, sizeof(int));
return mat;
}
and it should be called like
mat = alloc_matrix(n, m);
It is often said that one should not cast the result of calloc and friends. But in this case the cast has enabled a warning which helped to find a bug. I'm leaving the casts in place for now.
There is another idiom for the allocation that does not require the cast, but also avoids the problem of types not matching.
Instead of using the type for the sizeof, you can use the dereferenced pointer as the type information is available in the variable:
mat = (int**)calloc(n, sizeof(int*));
can be changed to
mat = calloc(n, sizeof *mat); //sizeof is an operator not a function
I was trying to run a simulation in which I need to fill three matrices of size "2 x iterations", this is (iterations=)10^8 columns and 2 rows. I also work with a vector t of size 10^8. Using dynamic memory allocation I wrote the following code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define T 10000
#define dt 0.0001
#define iterations (T/dt)
/*(more code)*/
int main(){
int i, j;
double *t;
double (*x)[2], (*y)[2], (*c)[2];
t=(double *) malloc((iterations-1)*sizeof(double));
x=(double (*)[2]) malloc((2*(iterations))*sizeof(double));
y=(double (*)[2]) malloc((2*(iterations))*sizeof(double));
c=(double (*)[2]) malloc((2*(iterations))*sizeof(double));
for(i=0; i=1; i++){
x[i][0]=50+500*i;
y[i][0]=300;
c[i][0]=15;
}
for(j=0; j<=iterations-2; j++){
t[j+1]=t[j]+dt;
/*(more code)*/
printf("%G %G %G %G %G %G\n",x[0][j+1],x[1][j+1],y[0][j+1],y[1][j+1],c[0][j+1],c[1][j+1]);
}
return 0;
}
Is the dynamic memory allocation correctly written? I mean, do I really have a vector t of size "iterations" and the three matrices of size "2 x iterations"?
And, if I want to fill each component of the matrices, for example I want a 50 in the position (1,4) of the matrix x, then do I have to write x[1][4]=50? (Like in the first "for".)
The problem is that executing the program I get an error: segmentation fault. Then, using a debugger I get the following:
Program received signal SIGSEGV, Segmentation fault.
x[0][0]=50
A generic way to allocate a matrix:
double **mat_init(int n_rows, int n_cols)
{
double **m;
int i;
m = (double**)malloc(n_rows * sizeof(double*));
for (i = 0; i < n_rows; ++i)
m[i] = (double*)calloc(n_cols, sizeof(double));
return m;
}
void mat_destroy(int n_rows, double **m)
{
int i;
for (i = 0; i < n_rows; ++i) free(m[i]);
free(m);
}
You can also do this:
double **mat_init2(int n_rows, int n_cols)
{
double **m;
int i;
m = (double**)malloc(n_rows * sizeof(double*));
m[0] = (double*)calloc(n_rows * n_cols, sizeof(double));
for (i = 1; i < n_rows; ++i)
m[i] = m[i-1] + n_cols;
return m;
}
void mat_destroy2(double **m)
{
free(m[0]); free(m);
}
For both methods above, you can use matrix[row][col] to access a cell. Sometimes, you may prefer to allocate a single array and use matrix[row*n_cols+col] to access a cell.
BTW, I am sure someone will say "don't use cast", but there are benefits of using cast – that is off-topic.
I mean, do I really have a vector t of size "iterations"
t=(double *) malloc((iterations-1)*sizeof(double));
^^^
Since you subtract one, the answer is no.
.... and the three matrices of size "2 x iterations"?
Well - yes you have three matrices of size "2 x iterations". However, what you have is equivalent to:
double m[iterations][2];
so you have "iterations" rows and 2 columns.
Remember to always check for "out of memory", i.e.
p = malloc(....);
if (p == NULL)
{
printf("out of mem\n");
return -1;
}
So you access it like:
m[0][0]
m[0][1]
m[1][0]
m[1][1]
m[2][0]
m[2][1]
m[3][0]
......
Okay. My original question turned out to be caused by not initializing some arrays. The original issue had to do with code crashing R. When I was trying to debug it by commenting things out, I by mistake commented out the lines that initialized the arrays. So I thought my problem had to do with passing pointers.
The actual problem is this. As I said before, I want to use outer_pos to calculate outer differences and pass both the pointers of the results and the total number of positive differences back to a function that calls outer_pos
#include <R.h>
#include <Rmath.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
void outer_pos(double *x, double *y, int *n, double *output){
int i, j, l=0;
for(i=0; i<*n; i++){
for(j=0; j<*n; j++){
if((x[j]-x[i])>0){
output[l+1]=(y[j]-y[i])/(x[j]-x[i]);
output[0]=(double)(++l);
}
}
}
Rprintf("%d\n", (int)output[0]);
}
void foo1(double *x, double *y, int *nsamp){
int i, j, k, oper=2, l;
double* v1v2=malloc(sizeof(double)*((*nsamp)*(*nsamp-1)/2 + 1));
outer_pos(x, y, nsamp, &v1v2[0]);
double v1v2b[1999000]; // <--------------HERE
for(i=1; i<= (int)v1v2[0]; i++){
v1v2b[i-1]=1;
}
}
Suppose foo1 is the function that calls outer_pos. Here I specified the size of the array v1v2b using an actual number 1999000. This value corresponds to the number of positive differences. Calling foo1 from R causes no problem. It's all fine.
In the scenario above, I know the number of positive differences, so I can use the actual value to set the array size. But I would like to accommodate situations where I don't necessarily know the value. foo2 below is intended to do that. As you can see, v1v2b is initialized using the first value of the array v1v2. Recall that the first slot of the output of outer_pos stores the number of positive differences. So basically I use this value to set v1v2's size. However, calling this function in R causes R to either show a stack overflow error or causes it to crash (see screen shot below)
void foo2(double *x, double *y, int *nsamp){
int i, j, k, oper=2, l;
double* v1v2=malloc(sizeof(double)*((*nsamp)*(*nsamp-1)/2 + 1));
outer_pos(x, y, nsamp, &v1v2[0]);
double v1v2b[(int)v1v2[0]]; //<--------HERE
for(i=1; i<= (int)v1v2[0]; i++){
v1v2b[i-1]=1;
}
}
So I thought, maybe it has to do with indexation. Maybe the actual size of v1v2b is too small, or something, so the loop iterates outside the bound. So I created foo2b in which I commented out the loop, and use Rprintf to print the first slot of v1v2 to see if the value stored in it is correct. But it seems that the value v1v2[0] is correct, namely 1999000. So I don't know what is happening here.
Sorry for the confusion with my previous question!!
void foo2b(double *x, double *y, int *nsamp){
int i, j, k, oper=2, l;
double* v1v2=malloc(sizeof(double)*((*nsamp)*(*nsamp-1)/2 + 1));
outer_pos(x, y, nsamp, &v1v2[0]);
double v1v2b[(int)v1v2[0]]; //<----Array size declared by a variable
Rprintf("%d", (int)v1v2[0]);
//for(i=1; i<= (int)v1v2[0]; i++){
//v1v2b[i-1]=v1v2[i];
//}
}
R code to run the code above:
x=rnorm(2000)
y=rnorm(2000)
.C("foo1", x=as.double(x), y=as.double(y), nsamp=as.integer(2000))
.C("foo2", x=as.double(x), y=as.double(y), nsamp=as.integer(2000))
.C("foo2b", x=as.double(x), y=as.double(y), nsamp=as.integer(2000))
** FOLLOW UP **
I modified my code based on Martin's suggestion to check if the stack overflow issue can be resolved:
void foo2b(double *x, double *y, int *nsamp) {
int n = *nsamp, i;
double *v1v2, *v1v2b;
v1v2 = (double *) R_alloc(n * (n - 1) / 2 + 1, sizeof(double));
/* outer_pos(x, y, nsamp, v1v2); */
v1v2b = (double *) R_alloc((size_t) v1v2[0], sizeof(int));
for(i=0; i< (int)v1v2[0]; i++){
v1v2b[i]=1;
}
//qsort(v1v2b, (size_t) v1v2[0], sizeof(double), mycompare);
/* ... */
}
After compiling it, I ran the code:
x=rnorm(1000)
y=rnorm(1000)
.C("foo2b", x=as.double(x), y=as.double(y), nsamp=as.integer(length(x)))
And got an error message:
Error: cannot allocate memory block of size 34359738368.0 Gb
** FOLLOW UP 2 **
It seems that the error message shows up every other run of the function. At least it did not crash R...So basically function alternates between running with no problem and showing an error message.
(I included both headers in my script file).
As before, you're allocating on the stack, but should be allocating from the heap. Correct this using malloc / free as you did in your previous question (actually, I think the recommended approach is Calloc / Free or if your code returns to R simply R_alloc; R_alloc automatically recovers the memory when returning to R, even in the case of an error that R catches).
qsort is mentioned in a comment. It takes as its final argument a user-supplied function that defines how its first argument is to be sorted. The signature of qsort (from man qsort) is
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
with the final argument being 'a pointer to a function that takes two constant void pointers and returns an int'. A function satisfying this signature and sorting pointers to two doubles according to the specification on the man page is
int mycompare(const void *p1, const void *p2)
{
const double d1 = *(const double *) p1,
d2 = *(const double *) p2;
return d1 < d2 ? -1 : (d2 > d1 ? 1 : 0);
}
So
#include <Rdefines.h>
#include <stdlib.h>
int mycompare(const void *p1, const void *p2)
{
const double d1 = *(const double *) p1,
d2 = *(const double *) p2;
return d1 < d2 ? -1 : (d2 > d1 ? 1 : 0);
}
void outer_pos(double *x, double *y, int *n, double *output){
int i, j, l = 0;
for (i = 0; i < *n; i++) {
for (j = 0; j < *n; j++) {
if ((x[j] - x[i]) > 0) {
output[l + 1] = (y[j] - y[i]) / (x[j] - x[i]);
output[0] = (double)(++l);
}
}
}
}
void foo2b(double *x, double *y, int *nsamp) {
int n = *nsamp;
double *v1v2, *v1v2b;
v1v2 = (double *) R_alloc(n * (n - 1) / 2 + 1, sizeof(double));
outer_pos(x, y, nsamp, v1v2);
v1v2b = (double *) R_alloc((size_t) v1v2[0], sizeof(double));
qsort(v1v2b, (size_t) v1v2[0], sizeof(double), mycompare);
/* ... */
}
When foo2b calls outer_pos, it is passing two allocated but uninitialized arrays as x and y. You can't depend on their contents, thus you have different results from different invocations.
Edit
You're dangerously close to your stack size with 1999000 doubles, which take just over 15.25MB, and that's because you're on Mac OS. On most other platforms, threads don't get anywhere near 16M of stack.
You don't start out with a clean (empty) stack when you call this function -- you're deep into R functions, each creating frames that take space on the stack.
Edit 2
Below, you are using an uninitialized value v1v2[0] as an argument to R-alloc. That you get an error sometimes (and not always) is not a surprise.
v1v2 = (double *) R_alloc(n * (n - 1) / 2 + 1, sizeof(double));
/* outer_pos(x, y, nsamp, v1v2); */
v1v2b = (double *) R_alloc((size_t) v1v2[0], sizeof(int));
I am writing a n x n matrix multiplication program in C where a[][] and b[][] are the inputs and x[][] is the output. a, b and x are malloc'd but I am unsure how to pass the pointers to the multiplication function correctly. below is an outline of what i am trying to do
void multiplication(float a, float b, float x, int n);
void main() {
float **a, **b, **x;
int n; // size of arrays (n x n)
multiplication(a, b, x, n);
}
void multiplication(float a, float b, float x, int n) {
// function
}
You want void multiplication(float *a, float *b, float *x, int n);. Note that generally you should use size_t for indexes and array sizes, and double as your preferred floating point type unless you have specific reason to use float.
Each of a, b and x point to contiguous float values, you will want to dereference these using a[n * x + y].
C99 introduces all kinds of interesting optimization possibilities on top of this, all of which you pretty much can't rely upon in any compiler I know of:
Variable Length Arrays in GCC
Arrays in XL C/C++ V7.0 (for AIX)
With those, something like this should be possible:
void multiplication(size_t len; // <- semicolon not a mistake
double a[len][restrict const len],
double b[len][restrict const len],
double c[len][restrict const len]);
This pedantic construction would indicate to the compiler that the length of the arrays are are the same, they're 2D, and the sizes are indicated from the calling code at runtime. Furthermore all the arrays are cacheable as they don't alias one another.
One can only dream that C continues to be advanced, C99 still isn't fully supported, and many other improvements haven't become mainstream.
you have to pass the address of first element of both matrix in multiplication method
actually the thing is that the elements of an array is arranged like queue means one element after another. so if you know the address of first element then you just increase the index number and you easily get all member of that array.
check this
it might be help you
Well, you must understand pointers for doing this kind of things in C. Here's a simple code:
int n = 10;
float * multiply ( float *a, float *b ) {
float *ans;
int i, j, k;
ans = malloc(sizeof(float)*n*n);
for (i=0; i<n; ++i)
for (j=0; j<n; ++j) {
ans[i*n+j] = 0.0;
for (k=0; k<n; ++k)
ans[i*n+j] += a[i*n+k] * b[k*n+j];
}
return ans;
}
int main() {
float *a, *b, *ans;
a = malloc(sizeof(float)*n*n);
input(&a);
b = malloc(sizeof(float)*n*n);
input(&b);
ans = multiply(a,b);
output(ans);
return 0;
}
If you have trouble understanding the code, please try to brush up your pointer skills. And you can always ask us.
Here is a nice easy way to pass dynamically allocated arrays to a function.
#include <stdio.h>
#include <stdlib.h>
void Function(int ***Array);
int main()
{
int i, j, k, n=10;
//Declare array, and allocate memory using malloc. ( Dimensions will be 10 x 10 x 10)
int ***Array=(int***)malloc(n*sizeof(int**));
for (i=0; i<n; i++)
{
Array[i]=(int**)malloc(n*sizeof(int*));
for (j=0; j<n; j++)
{
Array[i][j]=(int*)malloc(n*sizeof(int));
}
}
//Initialize array in a way that allows us to check it easily (i*j+k).
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
{
for (k=0; k<n; k++)
{
Array[i][j][k]=i*j+k;
}
}
}
//Check array is initialized correctly.
printf("%d\n", Array[4][5][6]);
//Pass array to Function.
Function(Array);
//Check that Function has correctly changed the element.
printf("%d\n", Array[4][5][6]);
return 0;
}
void Function(int ***Array)
{
//Check that Function can access values correctly.
printf("%d\n", Array[4][5][6]);
//Change an element.
Array[4][5][6]=1000;
}
I know this is not specific to your matrix multiplication, but it should demonstrate how to pass the array to the function. It is quite likely that your function would need to know the dimensions of the array, so pass those to it as well... void Function(int ***Array, int n) and call the function as Function(Array, n);