Playing around and trying to learn how arrays in C work, and just how C works in general. I wanted to make a function that returned a 2 element array and assign that array to a variable. first I did;
int make_array(int i) {
int out[2] = {i, i 1};
return (int) *out;}
int main(void) {
int arr[2] = { make_array(68) }; // should be {68, 69}
for (int i = 0; i < 2; i ) {
printf("%d, ", arr[i]);}
return 0;
>> 68, 0,
This was the only way I could find to write it without throwing an error, and it output 68, 0, instead of 68, 69,. So I tried this;
void make_another_array(int j, void *vp) {
int out[2] = {j, j 1};
memcpy(vp, &out, sizeof(int) * 2);}
int main(void) {
int *hotdog_water = malloc(sizeof(int) * 2);
make_another_array(68, hotdog_water);
for (int i = 0; i < 2; i ){
printf("%d, ", hotdog_water[i]);}
free(hotdog_water); hotdog_water = NULL;
return 0;}
The function saves the result somewhere instead of returning it. The end result seems to work the way I'd like it to, but not assigning a value from something returned from a function seems hacky. I'm sure there's a better way to do this specific thing, but is there anything fundamentally wrong with doing it this way? What problems would I run into if I wrote to where a pointer was pointing for everything instead of using return? Are there any use cases for copying the results instead of returning it?
CodePudding user response:
Returning data in space provided by the calling routine is normal and common. The standard C library includes several examples, such as:
scanf("%d%d", &a, &b)
stores values ina
andb
.frexp(float x, &e)
returns one value and stores another ine
.fread(array, size, number, stream)
providesnumber
values inarray
.
If you do wish to provide two values through the function-return-value mechanism, you can do this by using a structure:
struct foo { int v[2]; } make_array(int i)
{
return (struct foo) {{ i, i 1 }};
}
#include <stdio.h>
int main(void)
{
struct foo x = make_array(68);
for (int i = 0; i < 2; i)
printf("%d, ", x.v[i]);
printf("\n");
}
For large structures, a C implementation typically implements the return mechanism just as you suggest with pointers: Where the C code looks like the function returns a structure, in the assembly code, the calling routine provides space for the structure and actually passes a pointer to it as an argument the function. When returning, the function uses that pointer to fill in the return value.