2

I'm trying to return 4 pointers which are stored in another pointer from a function in C, but I get segmentation fault. Do anyone know how to do this?

That's the way I tried to do this:

//declaration of 5 pointers (int * ptr0, float * ptr1, ..., int * ptr4)

int * function()
{
    int * ptr;
    ptr = malloc(sizeof(int)*4);

    float * ptr1;
    ptr1 = malloc(sizeof(float)*4);

    float * ptr2;
    ptr2 = malloc(sizeof(float)*4);

    float * ptr3;
    ptr3 = malloc(sizeof(float)*4);

    int * ptr4;
    ptr4 = malloc(sizeof(int)*4);

    retunr ptr;
}

ptr0 = function();
ptr1 = ptr0[0];
ptr2 = ptr0[1];
//and so on...

Ok, I changed my program but now I can not write in the pointers anymore. I know this is a realy 'stupid' question but I realy dont know. Can someone help ?

3
  • if you want to return multiple values, you could return a struct or return them through the parameter list Commented Jun 21, 2016 at 14:47
  • Please show the whole code including the declarations. Commented Jun 21, 2016 at 14:47
  • possible duplicate: stackoverflow.com/questions/9144516/out-parameters-in-c Commented Jun 21, 2016 at 14:51

6 Answers 6

9

You can only return a singe value from a function. A simple solution is to return a struct that contains the desired pointers.

struct pointers {
    float* ptr1;
    float* ptr2;
    float* ptr3;
    // or perhaps an array instead:
    // float* f_ptrs[3];
    int*   ptr4;
}

struct pointers function() {
    struct pointers p;
    // initialize the members here
    return p;
}
Sign up to request clarification or add additional context in comments.

Comments

4
void ** function()
{
    void ** ptr;
    ptr = (void **)malloc(sizeof(void *)*4);

    ptr[0] = malloc(sizeof(float)*4);
    ptr[1] = malloc(sizeof(float)*4);
    ptr[2] = malloc(sizeof(float)*4);
    ptr[3] = malloc(sizeof(int)*4);

    return ptr;
}

12 Comments

@noName beware that ptr0[x] are void pointers. you'll need to cast them to work with inta and floats
No need to cast in C.
C implicitly converts to/from void-pointers to any other type.
casting may hide an error the compiler would catch in the absence of the cast.
@mvidelgauz & alk, oh I see ambiguity now. alk's comment seems to respond to mvidelgauz's comment which is about one thing, but alk is commenting on the line (void **)malloc(sizeof(void *)*4); from the answer. (deleting redundant comments)
|
3

i saw it wasn't mentioned, but you could also pass double pointers into the function and have the function fill them out, another way to return multiple values:

void function(int** p1, float** p2, float** p3, float** p4, int** p5)
{
    *p1 = malloc(sizeof(int)*4);

    *p2 = malloc(sizeof(float)*4);

    *p3 = malloc(sizeof(float)*4);

    *p4 = malloc(sizeof(float)*4);

    *p5 = malloc(sizeof(int)*4);
}

int* ptr1;
float* ptr2;
float* ptr3;
float* ptr4;
int* ptr5;

function(&ptr1, &ptr2, &ptr3, &ptr4, &ptr5);

3 Comments

No need to cast in C.
casting may hide an error the compiler would catch in the absence of the cast
ah my bad, i usually work with c++, i'll remove the casting, thanks
2

There are three choices, you could return a void** (basically, a pointer to an array of void* that you then cast), you can declare a struct that contain the pointers, then allocate and return a pointer to such a struct (then let the caller de-allocate the struct) or you can use a func(float **ptr0, float **ptr1, float **ptr2, int **ptr3) and assign your malloced memory to *ptr0, ...

Neither of these are perfect, depending on circumstances I would pick either solution 2 or solution 3, on the basis that it's going to end up messy remembering all the relevant casts and allowing the compiler to help you with types is a good idea.

Comments

1

What about this:

#include <stdlib.h>
#include <stdio.h>  /* for perror() */


int function(void ** ptrs, size_t n)
{
  int result = -1;

  pptrs[0] = malloc(...);
  if (NULL == ptrs[0])
  {
    goto err;
  }

  ...

  ptrs[n - 1] = malloc(...);
  if (NULL == ptrs[n - 1])
  {
    goto err;
  }

  result = 0;

err:

  return result;
}

int main(void)
{
  size_t n = 5;
  void * ptrs[n];
  for (size_t i = 0; i < n; ++n)
  {
    ptrs[n] = NULL;
  }

  if (-1 == function(ptrs, n))
  {
     perror("function() failed");
     exit(EXIT_FAILURE);
  }

  /* Do stuff. */

  /* Free memory where ptrs' are pointing to. */

  return EXIT_SUCCESS;
}

If VLAs are not supported change the beginning of main() to be:

#define N (5)

int main(void)   
{
  size_t n = N;
  void * ptrs[N] = {0};

  if (-1 == function(ptrs, n))
  {
    ...

Comments

1

You didn't fill *ptr, but even if you did, don't do this. Use std::tuple<> or pair of std::pair<>s - or return a struct.

Edit: since it's no more C++, just return a struct with the four fields.

2 Comments

since it's no more C++, just return a struct with the four fields. Which I would heartily recommend in C++ as well, because you get to give descriptive names for the members.
@user2079303: in C++, you'd simply say std::tie(ptr1, ptr2, ptr3, ptr4) = function(), but otherwise yes, I agree.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.