How to send array by value to function in c? - c

I tried something like :
typedef struct vec{
int sz;
int v[];
} ff;
int sum(struct vec z){
int o=0,i;
for(i=0;i<z.sz;i++)
o+=z.v[i];
return o;
}
int main(){
int test[]={10,1,2,3,4,5,6,7,8,9,10};
return sum((struct vec)test);
}
But this example code can't compile. How to send array by value (not ref throw pointer) to function?

You can't send an array by value in C. Every time you try to pass an array to a function, you'll pass the pointer to the first value.
To pass an array by value, you can cheat a little and encapsulate it in a struct, and send it by value (so it will be copied)... It's a dirty hack, as explained here, but well, if you really want that, it works.
Another way is to copy the array inside the function, with the pointer given.

In your example, you will need to specify the exact size of the array in the definition of struct vec, for example int v[10]. Also your initialization can be written better. Try this:
#define MAX_SIZE 50
struct vec {
int sz;
int v[MAX_SIZE];
};
int sum(struct vec z){
int i, o;
o = 0;
for(i=0; i<z.sz; i++) o += z.v[i];
return o;
}
int main(){
struct vec test = {10, {1,2,3,4,5,6,7,8,9,10}};
return sum(test);
}

While it's true that an array in C has a size, that size can only be accessed through the sizeof operator, and then only on the original array. You can't cast an array to a structure in the hopes that the compiler will fill in all fields.
In fact, it's actually impossible to pass an array to a function "by value". All arrays decays to pointers, so when you pass an array to a function that function receives a pointer. This decay to pointers is also why you can only use the sizeof operator on the original array, once it decays to a pointer the compiler have no idea that it's actually pointing to an array, so using the sizeof operator (even on something that points to an array) will return the size of the pointer and not what it points to.
In your case, it would be simpler to change your function to take two arguments, the pointer to the array and the number of entries in the array:
/* `array` is an array containing `elements` number of `int` elements. */
int sum(const int *array, const size_t elements)
{
...
}
int main(void)
{
...
printf("Sum = %d\n", sum(test, sizeof(test) / sizeof(test[0]));
}

Arrays are always passed by reference in C, you can't change that.
What you can do is make a copy of array and pass the new array in the function

As the others noted, the only way in C to pass an array by value is to use a struct with a fixed size array. But this is not a good idea, because the array size will be hardcoded into the struct definition.
However, you really should not try to pass arrays by value. Instead, what you should do is simply to declare your pointer parameter as const, like this:
int sum(size_t count, const int* array) {
While this does not pass the array by value, it clarifies the intent not to change the array, i. e. you can now treat sum() as if you were passing the array by value.
If your function does indeed not change the array (like your sum() function), using a const pointer comes for free, copying the array to pass it by value would just waste time.
If your function really wants to change a private copy, do so explicitely within the function. If the array won't get too large, you can simply allocate it on the stack, like so:
int doSomethingWithPrivateCopy(size_t count, const int* array) {
int mutableCopy[count];
memcpy(mutableCopy, array, sizeof(mutableCopy));
//Now do anything you like with the data in mutable copy.
}

Related

Passing down structures containing arrays, why does the value of the array name change?

Say I have a structure of:
typedef struct{
int data[5];
}ArrayList;
With a main function of:
int main(int argc, char *argv[]) {
ArrayList test = {1,2,3,4,5};
int x;
change(test);
return 0;
}
change function body:
void change(ArrayList arr){
printf("%d",arr.data);
}
The way I understand this is that since it's a pass by copy, it passes down the value of test, and arr takes that value.
Since int data[5] is an array, it can't actually pass down all its actual members at once, in this case, the integers, so it gives the address of the first member (test.data[0]). It can only do so one by one like data[0], data[1], ...
So I'm assuming that arr.data here should have the value as test.data (talking about the pointer to the first member, so the address).
But for some reason if I print the value of arr.data it's displaying a completely different address from test.data's value, and when I print the members of arr it has all the members of test.data.
I'm seeing it as something similar if I declared something like:
int data[5] = {1,2,3,4,5};
printf("%d", data);
change(data);
then
void change(int data[]){
printf("%d", data); // this would have the same value as the statement above.
}
How does arr.test get its value?
Function arguments are passed by value. A function parameter is a variable local to the function that is initialized with the value of the corresponding argument.
The argument test and the parameter arr are different objects. They are in different places in memory, and the arrays in them are in different places in memory, so they have different addresses.
Since int data[5] is an array, it can't actually pass down all its actual members at once,…
This is not correct. C does not provide any feature for you to copy an array by its “value” (which is an aggregate “value” of all its members), but you can copy a structure containing an array, and that will copy the contained array.
Incidentally, to print addresses properly, convert them to void * and format them with %p: printf("%p\n", (void *) arr.data);.

how to pass 2d array address to a function and write on it and print it in calling function

I have a function that simply takes 2d char array write on first element [0][0] to n and m element and in main I like to print what has been written. I only need to pass the address of entire two dimensional array and use it in calling function.
This is what I tried so far with multiple variations of tries but nothing seems to work
folloing code cause segFault
I got segFault at array[0][0]='c'; in the called function. please note I need to pass only the address of 2d array so I can easily move around and populate the array in called function.
void bps(char **array,int m, int n)
{
array[0][0]='c';
}
I also tried like this *array[0]='c'; but no luck so far
I am passing array like bps(array,x,y); in main
this is the code in main
int main()
{
int x=3,y=3;
char array[3][3]={"ab","ax"};
// Or should I use like this
// char array[3][3]=(char [3][3]){"ab","ax"};
bps(array,x,y);
printf("%c",array[0][0]);
return 0;
}
or should I use like this in bps(..)
void bps(char *array,int m, int n )
{
*(*(array))='c';
}
please clarify
char** may be used for 1D arrays of pointers, such as pointing in the first item in an array of strings. But it cannot be used to point at a 2D array. Forget that you ever heard of type** in relation to 2D arrays.
Change void bps(char **array,int m, int n) to:
void bps (int m, int n, char array[m][n])
Access individual items with array[i][j], not with obscure and unreadable pointer arithmetic like *(*(array))='c';.
Detailed explanation:
The reason why char array[m][n] works is that arrays, whenever used as a function parameter, get implicitly adjusted ("decays") to a pointer to their first element by the compiler.
Given an array char array[m][n], it is an array of arrays. The first item is therefore an array of type char[n]. A pointer to that first item type is written as char (*)[n]. Therefore
void bps (int m, int n, char array[m][n])
is 100% equivalent to
void bps (int m, int n, char (*array)[n])
And in either case the array is passed "by reference", not by value as one might incorrectly suspect.

How do I correctly return an array from a function?

I tried this:
int* test()
{
static int states[2]= {4,7};
return states;
}
And called it like this:
int* values = test();
But it only seems to return the first value - 4 - and not the whole array.
I tried to do it exactly as I saw in other examples so I'm confused as to why it doesn't work. I'm using the STM32cubeIDE to write and compile, if that makes a difference.
Normal arrays can't be returned from a function because their lifetime ends when the function returns, the behavior for accessing one of these local arrays outside the scope of the function is undefined.
In your particular case this is possible because your array has static storage duration.
In C a function can only return one element, so to return an array you must return a pointer which can contain the address of the first element of that array. And that's what you're doing in your code. You can access both values by correctly indexing the returned pointer i.e. values[0] and values[1].
Unfortunately this is not without its issues, the size of the array is not known by the caller and you can't safely index it because you don't know its bounds.
There are ways solve this which are not all that complicated once you get used to them. Most notably defining a global size for the array1, using a structure containing the size of the array and a pointer to the array itself2, or passing pointers to the size and/or the array as arguments of the function3.
1. Using a global variable that stores its size:
#define SIZE 2
int *test()
{
static int states[SIZE] = {4, 7};
return states; //returns a pointer to the first element of the array
}
int main()
{
int* values = test(); // values is now pointing to the array
for(size_t i = 0; i < SIZE; i++){
printf("%d ", values[i]); //indexing is similar to a local array
}
}
2. Using a struct to store both the size and a pointer to the array:
typedef struct{ //structure to hold the data
int *array;
size_t size;
} array_struct;
array_struct test()
{
static int states[2] = {4, 7};
array_struct array = {.array = states, .size = 2}; //assing pointer and size
return array; //return the structure
}
int main()
{
array_struct values = test(); //assing the structure to a local
for(size_t i = 0; i < values.size; i++){ //use the size passed
printf("%d ", values.array[i]);
}
}
Output:
4 7
Option 3 is laid out in Bathsheba's answer.
You get back a pointer to the first element of the array due to the decay of the array type to a pointer type.
You obtain the other elements by pointer arithmetic.
Unfortunately though all size information is lost so you don't know at the call site how many elements you have. One way round that would be to change the function to
void test(int** array, size_t* length)
with *array = states and *length = sizeof(states) / sizeof(states[0]) in the function body.
How do I correctly return an array from a function?
You don't because you cannot. Read the C11 standard n1570.
(since as return values, arrays are decayed to pointers)
In practice, you could use a flexible array member in your struct and return some malloc-ed pointer to that struct. You then need a documented convention about who will free that pointer.
Read about C dynamic memory allocation. For more details and example code, see this answer.

Passing dynamically allocated array as a parameter in C

So... I have a dynamically allocated array on my main:
int main()
{
int *array;
int len;
array = (int *) malloc(len * sizeof(int));
...
return EXIT_SUCCESS;
}
I also wanna build a function that does something with this dynamically allocated array.
So far my function is:
void myFunction(int array[], ...)
{
array[position] = value;
}
If I declare it as:
void myFunction(int *array, ...);
Will I still be able to do:
array[position] = value;
Or I will have to do:
*array[position] = value;
...?
Also, if I am working with a dynamically allocated matrix, which one is the correct way to declare the function prototype:
void myFunction(int matrix[][], ...);
Or
void myFunction(int **matrix, ...);
...?
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
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)).
Will I still be able to do:
array[position] = value;
Yes, because the index operator p[i] is 100% identical to *(ptr + i). You can in fact write 5[array] instead of array[5] and it will still work. In C arrays are actually just pointers. The only thing that makes an array definition different from a pointer is, that if you take a sizeof of a "true" array identifier, it gives you the actual storage size allocates, while taking the sizeof of a pointer will just give you the size of the pointer, which is usually the system's integer size (can be different though).
Also, if I am working with a dynamically allocated matrix, which one is the correct way to declare the function prototype: (…)
Neither of them because those are arrays of pointers to arrays, which can be non-contigous. For performance reasons you want matrices to be contiguous. So you just write
void foo(int matrix[])
and internally calculate the right offset, like
matrix[width*j + i]
Note that writing this using the bracket syntax looks weird. Also take note that if you take the sizeof of an pointer or an "array of unspecified length" function parameter you'll get the size of a pointer.
No, you'd just keep using array[position] = value.
In the end, there's no real difference whether you're declaring a parameter as int *something or int something[]. Both will work, because an array definition is just some hidden pointer math.
However, there's is one difference regarding how code can be understood:
int array[] always denotes an array (it might be just one element long though).
int *pointer however could be a pointer to a single integer or a whole array of integers.
As far as addressing/representation goes: pointer == array == &array[0]
If you're working with multiple dimensions, things are a little bit different, because C forces you declare the last dimension, if you're defining multidimensional arrays explicitly:
int **myStuff1; // valid
int *myStuff2[]; // valid
int myStuff3[][]; // invalid
int myStuff4[][5]; // valid

Decayed multidimensional array return from function

related to (gcc) Multi-Dim Array or Double Pointer for Warning-free Compile , is there a way to return so-called "decayed array pointer" from a function? in summary (suppose 2 dim array) returning int (*a)[5] format rather than int** format?
as far as I see, when returned int** pointer is sent to another function waiting (int*)[] parameter, it is not working correctly.
Yes, but the syntax won't look nice
int(*f())[5] {
static int a[1][5] = { { 1, 2, 3, 4, 5 } };
return a;
}
Basically, it's just your a replaced by f() (a function). Using a typedef it becomes more readable
typedef int inner_array[5];
inner_array *f() {
// like before ...
}
Notice that to denote the abstact type, without a name, you need to write int(*)[5]. That is, you just erase the name. (int*)[5] is not valid syntax.
You are right - you can't return int** because this means you have a pointer to a pointer. Accessing with f()[A][B] would read from the address the returned pointer gives, and then read again from the address given by that pointer in turn. But in fact, the array pointer you return points only to one memory block, so if you would make two indirections, you would try to reinterpret data as being pointers.
Contrary, if you return a int(*)[5] and do f()[A][B] you will not read any value from the address returned by the pointer. Instead, you merely add the offset A to the address, and adjust the type from int(*)[5] to int[5] to have an array that refers to memory at the adjusted address. The next index will then again adjust by B and since it operates on a int* then (after the array decayed), not anymore on an array pointer, it will then read the content stored at the adjusted address, to finally yield the int. This is an important difference of non-array pointers and array pointers.
You can experiment with this, if you want. Consider these two snippets. One will probably crash, but the other probably won't (but both yield undefined behavior, so this shouldn't be done in real programs)
int *pi = 0;
int(*pa)[5] = 0;
int i = *pi; // read int stored at null-pointer address!
int *a = *pa; // does not read any data from address, just adjusts the type!
struct thing {
int A[10][10];
};
typedef struct thing thing_t;
thing_t f1(void) {
thing_t t;
...
return t;
}
thing_t * f1(void) {
thing_t * tp;
...
return tp;
}
Though, you're really going about this the wrong way.

Resources