Home > Software design >  C - using memcpy in function to assign value instead of return
C - using memcpy in function to assign value instead of return

Time:08-11

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 in a and b.
  • frexp(float x, &e) returns one value and stores another in e.
  • fread(array, size, number, stream) provides number values in array.

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.

  • Related