Defining 2D array using pointers with adjacent memory - c

I thought of doing
int arr[row][col];
But I guess since I am to pass the entire arr to a function multiple number of times, hence it may give me stackoverflow [since ROW and COL can be a few thousands]. Hence if I do it using pointers instead then passing on the pointer would be a better way , since I also intend to change the values of the array as it passes through various functions.
How do I define the array using pointer and how do I pass it to the function? Intend to do arr[i][j] whenever I want to access an element.

When you pass arrays around as arguments, you only pass a pointer to its first element, not the entire array.
So the function signature could look something like this:
void some_function(int arr[][col]);
Or optionally
void some_function(int (*arr)[col]);
If the column size is not a global compile-time constant, then you can pass it as argument to the function as well:
void some_function(const size_t col, int arr[][col]);
Or
void some_function(const size_t col, int (*arr)[col]);

Passing the array to a function is OK. Arrays are treated like pointers when passing as argument, that is, only the address of the first element is copied.
But be sure to pass number of rows and columns as arguments too.

Related

Sentinels in non-pointer arrays

Let's say I have the following array:
int numbers[] = {-2,4,9,11};
int sum=sum_list(numbers);
If I were to pass pointers, I could add in a NULL at the end of the list to signal the size of it. However, in the above non-pointer list, is there a way to do that? If not, is the way around this just to explicitly pass the size of the array to the callee, for example:
int sum_list(int numbers[], size_z len);
When dealing with an array of non-pointer values such as this, you basically have two choices:
Pass the length of the list to any function that also receives the list
Designate some value that is outside the range of acceptable values to use as an end-of-list indicator
A third choice would be to implement a Pascal-type array where index 0 contains the length of the array.

"Indexed" array function argument in C

I recently saw a function written in the following form void func(int size, int a[size]){ ... } and I was curious about the argument a[size]. At first I thought maybe it had something to do with indexing the array, but running the code a was in fact an array. Then I thought maybe it had to do with the size of the array, so I tried passing in different value and seeing if it would affect the array length, but it seemed not to (unless maybe it had something to do with writing past the array, but this feels unlikely). So my question is essentially, what does the "index" do in the function arguments?
It's the array size, but it's ignored when it's in a function parameter declaration. A function parameter of the form int a[size] or int a[] is treated identically to int *a, because arrays decay to pointers when used as function arguments.
So it's essentially just a form of self-documentation. The caller is supposed to pass an array that contains size elements.
Note that this only applies to the first dimension in a multidimensional array parameter. If you have something like
void func(int width, int height, int a[height][width]) { ... }
The width part of the array declaration is used, but the height is ignored. a is a pointer to an array of int[width] rows; the width is needed when indexing the first dimension.

Use pointer to change an array when passing it into a method

Suppose I am writing a sorting-array method. At the time I did not know pointer, I usually defined array as global so that it automatically change.
Now I try to use it but it fails, basically it ends up with
int a[5];
sort(&a); // Calling sort
...
// My method
void sort(int *a[]) {
int key = *a[1]; // I've got a bug right here
...
}
I am still unfamiliar with using pointers. Moreover I can not use reference, either. Please suggest me some ways to do that.
Thank you so much.
Change your function to just this :: void sort(int *a) or this :: void sort(int a[])
And when you call sort from the main, you need not call sort(&a), a is an array pointer itself, calling sort(a) will do it!
Both your passing and using of array are not correct. An array name gets converted into a pointer to its first element. So passing the name is sufficient to modify it, not a pointer to array (You can pass a pointer to array too -- but has to used accordingly in the function and is usually not needed to modify elements of an array).
Call it:
sort(a);
and use it:
void sort(int a[]) {
int key = a[1];
...
}
In sort(), you can use it with the usual array notation.
One thing to note is that you can't get the size of the array in sort() using sizeof operator as all the size information is lost in sort() and all you have is a pointer. So you have to pass the array size as an additional argument.
Using the square bracket notation with an index deferences the pointer (put simply, gives you the variable rather than the address), so you shouldn't have an asterisk there. The following are equivalent (but only for 0!):
*a
a[0]
If you are in fact trying to use the value of the second element (index 1) in key, then you should use:
int key = a[1];
Additionally, since a is an address, &a is not useful to you and you should be calling the sort function with only a.

how to define a 2d array using malloc and pass it to a function

I want to pass a 2d array i defined using malloc to a function.
First i define the array using code from a blog post.
int** Make2DIntArray(int arraySizeX, int arraySizeY) {
int** theArray;
theArray = (int**) malloc(arraySizeX*sizeof(int*));
for (int i = 0; i < arraySizeX; i++)
theArray[i] = (int*) malloc(arraySizeY*sizeof(int));
return theArray;
}
int main(){
int** myArray = Make2DIntArray(nx, ny);
}
I can then use it as myArray[i][j].
After that,i want to pass this array to a function.I tried to pass it like this:
function(myArray); //function call
//function
void function(int myArray[][]){
//function code goes here
}
but this is wrong.The problem is that the size of the array is different every time.I also tried to define a maximum size for the columns of the array and use it like this:
#define COLUMNMAX 100
function(myArray); //function call
//function
void function(int myArray[][COLUMNMAX]){
//function code goes here
}
but i got the error:
type of formal parameter 1 is incomplete.How can i pass it?
The parameter is a int**
And you don't have to cast the return of malloc, just check if it's not NULL
But since you use malloc don't use free when you don't need it anymore
myArray bounds are not know so you should change void function(int myArray[][]){ to void function(int **myArray){.
Do not make typecasting of malloc
The C standard supports variable-length arrays, so you do not need to allocate, assign, or use extra pointers. Simply specify the dimensions you want, as shown below.
Allocate an array of M rows of N columns like this:
int (*array)[N] = malloc(M * sizeof *array);
Declare a function that is receiving such an array like this:
void function(size_t M, size_t N, int array[][N]);
Pass the array to the function like this:
function(M, N, array);
What you do with Create2DIntArray is not an actuall 2d array. It's just an array of pointers, each pointing to some place in memory. And every piece of memory is allocated separately with separate malloc call (BTW, don't forget to free it). So basically there's no guarantees, that there bits are allocated consequentionally and properly alligned as with int myArray[][]. The only way to pass your data as a 2d array, I guess, would be to create a real 2d array and refill it with your data.
To get rid of your "type of formal parameter 1 is incomplete." error, you should declare your function before you use it (forward declaration):
void functionB(int **myArray); //forward declaration
void functionA() {
functionB(blaaaa); //usage
}
void functionB(int **myArray) {
//implementation
}
It looks like what you're needing here is some booking information for the size of the rows and columns in the array. There are multiple ways to do that, but here are four)
1) If you know the size at compile time, you could use a define like you tried to do. Defines are globally scoped, you can access them in all your functions in a file. Instead of somehow trying to pass the defined value (like COLUMN_SIZE ) simply use it as a for loop end-condition inside your "function" function. However, if you know the size before compile time, you might as well simply make an array of fixed size. Malloc is usually meant for dynamic run-time determined memory allocation.
2) Simply store the values of nx and ny in main, and make it so that "function" takes 3 arguments: (int[][] my_array, column_size, row_size) and pass it your pointer to the array as well as nx and ny. This is preferable than method 1, because it allows for an array size to be specified during runtime, not during compile time.
3)This is the one I would recommend: Use a structure, like this
struct 2d_array{
int row_size;
int column_size;
int** actual_array;
}
With this, you have a few options. You could edit Make2dIntArray so that it returns either a 2d_array structure or a pointer to a 2d_array structure (depending on if you want to handle the structure with pass by reference or pass by value). Or you could have it so that you construct the structure in main. I'd advise having Make2dIntArray return the structure, it would be very clean.
And then you could have your "function" function simply take a 2d_array structure as it's argument (again, either as a pointer or not, depending on if you want to change the row_size and column_size variables, which I can't see any purpose for unless you remalloc actual_array). Then you just access the row_size and column_size variables in the structure inside "function" and you have all the information you need.
Basically, the whole idea behind this is book-keeping. Keep track of the information you need, and make it easily accessible when you need it.

Is it possible to pass a pointer to and array as a function parameter?

I have two integer arrays created at runtime (size depends on the program input). At some point I need to update the contents of an array with the contents of the other doing some calculations.
First I thought about passing those arrays as parameters to a function because I didn't find a way to return functions in C (don't think it's possible). After realizing that was a bad idea since parameters are not really modifiable as they're copied to the stack I resorted to change to array pointers instead.
While the function is still empty, this is the code I have:
1st take (code compiles, no errors):
// Elements is just to be able to iterate through their contents (same for both):
void do_stuff(int first[], int second[], int elements) {}
// Call to the function:
do_stuff(first, second, elements);
2nd take, attempt to translate to pointers to be able to modify the arrays in place:
void do_stuff(int *first[], int *second[], int elements) {}
// Call to the function:
do_stuff(&first, &second, elements);
This code lead to some rightful compile time errors, because apparently what I thought to be pointer to arrays were arrays of pointers.
3rd take, what I think it'd be the right syntax:
void do_stuff(int (*first)[], int (*second)[], int elements) {}
// Call to the function:
do_stuff(&first, &second, elements);
Still this code produces compile time errors when trying to access the elements of the arrays (e.g. *first[0]):
error: invalid use of array with unspecified bounds
So my question is regarding the possibility of using an array pointer as a parameter of a function, is it possible? If so, how could it be done?
Anyway, if you think of a better way to update the first array after performing calculations involving the contents of the second please comment about it.
An array decays to a pointer to the data allocated for the array. Arrays are not copied to the stack when passing to functions. Thus, you needn't pass a pointer to the array. So, the below should function fine.
// Elements is just to be able to iterate through their contents (same for both):
void do_stuff(int first[], int second[], int elements) {}
// Call to the function:
do_stuff(first, second, elements);
The cause of your errors on your second attempt are because int *first[] (and the others like it) are actually of the type array of pointer to int.
The cause of your third errors are because *first[N] is actually *(first[N]), which cannot be done with ease. Array access is really a facade over pointer arithmetic, *(first + sizeof first[0] * N); however, you have an incomplete element type here -- you need to specify the size of the array, otherwise sizeof first[0] is unknown.
Your first attempt is correct. When passing an array as a parameter in C, a pointer to the first element is actually passed, not a copy of the array. So you can write either
void do_stuff(int first[], int second[], int elements) {}
like you had, or
void do_stuff(int *first, int *second, int elements) {}
In C arrays automatically decay to pointers to data, So, you can just pass the arrays and their lengths and get the desired result.
My suggestion is something like this:
void dostuff(int *first, int firstlen, int *second, int secondlen, int elements)
Function call should be:
do_stuff(first, firstlen, second, secondlen, elements);
I am not very clear from your question, why you need elements. But, you must pass array lengths as arrays automatically decays to pointers when passed to a function, but, in the called function, there is no way to determine their size.

Resources