If I declare it as:
void myFunction(int *array, ...);Will I still be able to do:
array[position] = value;
Yes - this is legal syntax.
Also, if I am working with a dynamically allocated matrix, which one is correct to declare the function prototype:
void myFunction(int matrix[][], ...);Or
void myFunction(int **matrix, ...);...?
If you're working with more than one dimension, you'll have to declare the size of all but the first dimension in the function declaration, like so:
void myFunction(int matrix[][100], ...);
This syntax won't do what you think it does:
void myFunction(int **matrix, ...);
matrix[i][j] = ...
This declares a parameter named matrix that is a pointer to a pointer to int; attempting to dereference using matrix[i][j] will likely cause a segmentation fault.
This is one of the many difficulties of working with a multi-dimensional array in C.
Here is a helpful SO question addressing this topic: Define a matrix and pass it to a function in C
Answer from Tom on Stack OverflowIf I declare it as:
void myFunction(int *array, ...);Will I still be able to do:
array[position] = value;
Yes - this is legal syntax.
Also, if I am working with a dynamically allocated matrix, which one is correct to declare the function prototype:
void myFunction(int matrix[][], ...);Or
void myFunction(int **matrix, ...);...?
If you're working with more than one dimension, you'll have to declare the size of all but the first dimension in the function declaration, like so:
void myFunction(int matrix[][100], ...);
This syntax won't do what you think it does:
void myFunction(int **matrix, ...);
matrix[i][j] = ...
This declares a parameter named matrix that is a pointer to a pointer to int; attempting to dereference using matrix[i][j] will likely cause a segmentation fault.
This is one of the many difficulties of working with a multi-dimensional array in C.
Here is a helpful SO question addressing this topic: Define a matrix and pass it to a function in C
Yes, please use array[position], even if the parameter type is int *array. The alternative you gave (*array[position]) is actually invalid in this case since the [] operator takes precedence over the * operator, making it equivalent to *(array[position]) which is trying to dereference the value of a[position], not it's address.
It gets a little more complicated for multi-dimensional arrays but you can do it:
int m = 10, n = 5;
int matrixOnStack[m][n];
matrixOnStack[0][0] = 0; // OK
matrixOnStack[m-1][n-1] = 0; // OK
// matrixOnStack[10][5] = 0; // Not OK. Compiler may not complain
// but nearby data structures might.
int (*matrixInHeap)[n] = malloc(sizeof(int[m][n]));
matrixInHeap[0][0] = 0; // OK
matrixInHeap[m-1][n-1] = 0; // OK
// matrixInHeap[10][5] = 0; // Not OK. coloring outside the lines again.
The way the matrixInHeap declaration should be interpreted is that the 'thing' pointed to by matrixInHeap is an array of n int values, so sizeof(*matrixInHeap) == n * sizeof(int), or the size of an entire row in the matrix. matrixInHeap[2][4] works because matrixInHeap[2] is advancing the address matrixInHeap by 2 * sizeof(*matrixInHeap), which skips two full rows of n integers, resulting in the address of the 3rd row, and then the final [4] selects the fifth element from the third row. (remember that array indices start at 0 and not 1)
You can use the same type when pointing to normal multidimensional c-arrays, (assuming you already know the size):
int (*matrixPointer)[n] = matrixOnStack || matrixInHeap;
Now lets say you want to have a function that takes one of these variably sized matrices as a parameter. When the variables were declared earlier the type had some information about the size (both dimensions in the stack example, and the last dimension n in the heap example). So the parameter type in the function definition is going to need that n value, which we can actually do, as long as we include it as a separate parameter, defining the function like this:
void fillWithZeros(int m, int n, int (*matrix)[n]) {
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
matrix[i][j] = 0;
}
If we don't need the m value inside the function, we could leave it out entirely, just as long as we keep n:
bool isZeroAtLocation(int n, int (*matrix)[n], int i, int j) {
return matrix[i][j] == 0;
}
And then we just include the size when calling the functions:
fillWithZeros(m, n, matrixPointer);
assert(isZeroAtLocation(n, matrixPointer, 0, 0));
It may feel a little like we're doing the compilers work for it, especially in cases where we don't use n inside the function body at all (or only as a parameter to similar functions), but at least it works.
One last point regarding readability: using malloc(sizeof(int[len])) is equivalent to malloc(len * sizeof(int)) (and anybody who tells you otherwise doesn't understand structure padding in c) but the first way of writing it makes it obvious to the reader that we are talking about an array. The same goes for malloc(sizeof(int[m][n])) and malloc(m * n * sizeof(int)).
In C, everything is passed by value. In your concrete example arr is. You don't have references like in C++ or Java.
Let's take a C++ example:
void foo(int& i) {
++i;
}
int main() {
int i = 1;
foo();
}
Here, true references are used. i is passed by reference and foo modifies i over a reference to i. No "copying by value" takes place.
OTOH, in C, you don't have references. You can only write something like
void foo(int* i) {
++*i;
}
int main() {
int i = 1;
foo(&i);
}
To pass something "by reference"1 in C, you need to pass a pointer to it, just like you did. The pointer itsself is passed by value but it refers to a memory area (here i) modifiable by both the function and the allocator.
In the end, if you want to pass something "by reference" in C, copying by value is always involved. Not so in C++.
Quoting from K&R, 1.8 Arguments - Call by Value:
In C, all function arguments are passed by value.''
1 Note that this is within double quotes. C doesn't have "pass-by-reference." Period.
It is "both":
The pointer is passed by value, the array "by reference".
C Standard draft, N1256:
6.5.2.2 Function calls
...
4 An argument may be an expression of any object type. In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument.
...
I put "both" and "by reference" in quotes, because there are no references in C. A pointer is not a reference, but when used to "pass an array" to a function, it is roughly comparable, in the sense that if the function modifies the array, the changes are visible to the caller. I think this helps understanding what happens here.
We say that an array decays to a pointer, when passed to a function. "Decay" because the pointer looses some information, namely the length of the array. So saying this is similar to "pass by reference" is meant only from an application point of view.
c - How to pass a 2D dynamically allocated array to a function? - Stack Overflow
c - Passing a dynamically allocated array from main to another function - Stack Overflow
Passing two different dynamically allocated arrays to function in C - Stack Overflow
Dynamically allocated arrays and why they need to be passed by reference to be used in a function / pointer review
Videos
See the code below. After passing the 2d array base location as a double pointer to myfunc(), you can then access any particular element in the array by index, with s[i][j].
#include <stdio.h>
#include <stdlib.h>
void myfunc(int ** s, int row, int col)
{
for(int i=0; i<row; i++) {
for(int j=0; j<col; j++)
printf("%d ", s[i][j]);
printf("\n");
}
}
int main(void)
{
int row=10, col=10;
int ** c = (int**)malloc(sizeof(int*)*row);
for(int i=0; i<row; i++)
*(c+i) = (int*)malloc(sizeof(int)*col);
for(int i=0; i<row; i++)
for(int j=0; j<col; j++)
c[i][j]=i*j;
myfunc(c,row,col);
for (i=0; i<row; i++) {
free(c[i]);
}
free(c);
return 0;
}
If your compiler supports C99 variable-length-arrays (eg. GCC) then you can declare a function like so:
int foo(int cols, int rows, int a[][cols])
{
/* ... */
}
You would also use a pointer to a VLA type in the calling code:
int (*a)[cols] = calloc(rows, sizeof *a);
/* ... */
foo(cols, rows, a);
Here:
CalcE(&E, iterations);
you take address of E (of type long double *) and pass it as an argument to CalcE. CalcE accepts as first parameter a pointer to long double. But when you take an address of E you are given actually a pointer to pointer to long double (long double**), and that is not a pointer to long double. And this is what your error tells you:
error: cannot convert ‘long double**’ to ‘long double*’ for argument ‘1’ to ‘void CalcE(long double*, int)’ CalcE( &E, iterations );
So you should have:
CalcE(E, iterations);
CalcE(&E, iterations);
should be
CalcE(E, iterations);
Hope I helped
NOTE: This is about an EXAM THAT HAS ALREADY HAPPENED THERE IS NO CHEATING INVOLVED
Hello everyone I hope this post finds you all well. I had an exam today for one of my computer science classes 20% of the exam grade is just explaining your code, I was able to complete the prompt to the best of my ability but I could not explain for the life of me why I passed by reference a dynamically allocated array (I just knew it was something I had to do and I did it off instinct) And I wanted a deeper explanation on if we were to use a dynamically allocated array as a parameter for a function why would we need to pass it by reference. Along with I wanted to know any odd quirks that pointers have in relation to their syntax. I'm going to put my code, the outputs from it, and the prompt in a google doc below (note the prompt is at the bottom of the doc)
When writing:
int *anArray[100];
anArray[100] = new int [100];
In the first line, you are allocating an array of 100 pointers to int. In the second line, you dynamically allocating an array of ints and assigning the address of that array to the 100 cell of the array of pointers. Proper syntax would be:
int *anArray;
anArray = new int [100];
Array indexing starts from 0.
Array of len 100 has indexes from 0 to 99.
So anArray[100] gives you Segmentation Fault.
May be you want to do this:
anArray[99] = new int[100];
OR if you just want to dynamically allocate an array of pointer to ints, do that following:
int **anArray = new int*[100];