How to write a function that returns an array?

Hi,
I want to make a function that returns an array.
For example, something like this:

int TestArray=0;
int BuildArray()
{int MyArray[10]={0,1,2,3,4,5,6,7,8,9};
return MyArray;}

void setup()
{
Serial.begin(9600);
TestArray=BuildArray();
for (int i=0;i<10;i++)
{Serial.println (TestArray*);}*
}
*void loop() *
{}
Thanks for your help

1 Like

A function doesn't only get called once so I really don't know how to help you with that. You only called that function once so why making it into a function? Tell us the complete story, what you are trying to do, the whole picture, and how an array-returning function helps your goal?

You only called that function once so why making it into a function?

Make code more readable to name an imho important one?

You better maka a function that fills an array, like this

int FillArray(int * ar, int size)
{
  int t = 0;
  for (int i=0; i< size; i++)
  {
     ar[i] = t*t++;
  }
}

If you really want to create an array in a function you are entering the land of dynamic memory, pointers, malloc, free, but also memoryLeaks and dangling Pointers.

int * createArray(uint8_t size)
{
  if (size > 0) 
  {
    int* p = (int*) malloc(size * sizeof(int));
    for (int i = 0; i< size; i++) *p++ = i*i;
    return p;
  }
  return null;
}

please read (and buy) - http://letrongngoc.tech.officelive.com/Documents/TheCProgrammingLanguageSecondEdition.pdf -

To have general function the array would need to be dynamically allocated (search malloc, calloc, etc...); however, using your example you could do something like below:

int * BuildArray(i)
{
static int MyArray[] = {0,1,2,3,4,5,6,7,8,9};
return &MyArray;
}

The static declaration is necessary in this case to preserve the data when called after the function is exited. If your primary goal is to improve readability, in this case encapsulating the array (data) into a class that holds the data and provides methods for accessing it might be a better approach.

This is where I get confused. The OP has not offered any details and we are already offering possible solutions with actual code.

Rob, you have a good point. Let's wait a bit for the OP to respond with some details.

Thanks for the answers, of course the code is a simplified one and i gonna use the function in several places inside the loop.
I want to make a function that returns an array not only a number, i want to call once the function and take two or more data from it. I am an arduino user, my programmming skills are limited so I need an example.
I have remake the code whith yoru help and now it looks like this:

   int * BuildArray()
    {static int MyArray[10]={0,1,2,3,4,5,6,7,8,9};
      return MyArray;}   

void setup()   
{
int TestArray[10]={0,0,0,0,0,0,0,0,0,0};
  Serial.begin(9600);
    TestArray=BuildArray();
      for (int i=0;i<10;i++)
      {Serial.println (TestArray[i]);}
 }
void loop()                     
{}

Now there is no error in "int * BuildArray() ", I dont know what "int * " means, but it still has a bug in:

TestArray=BuildArray();

error: incompatible types in assignment of 'int*' to 'int [10]

thanks for your quick answers.

Moderator edit: [code] ... [/code] tags added. (Nick Gammon)

You can't really return an array without using dynamic memory allocation (malloc/free).

But you can modify an existing one like this:

void playWithArray (int (& myarray) [10] )
  {
  for (int i = 0; i < 10; i++)
     myarray [i] += 42; 
  }
  
void setup ()
 {
 int TestArray[10]={0,0,0,0,0,0,0,0,0,0};
  
  playWithArray (TestArray);
 }
 
void loop () {}

This passes the array by reference, which means changes you make affect the original array.

1 Like

Great,
I have solved, whit the forum help. This code works, I still dont know if arduino can return an array, but you can buid inside a function, of course you have to declare the array outside the function and the program.

int TestArray[10]={0,0,0,0,0,0,0,0,0,0};

 int  BuildArray(int MyArray[10])
    { 
 for (int i=0;i<10;i++)
  {TestArray[i]=i;}
    }   

void setup()   
{
  Serial.begin(9600);
    BuildArray(TestArray);
      for (int i=0;i<10;i++)
      {Serial.println (TestArray[i]);}
 }
void loop()                     
{}

Thanks and good job

Why is BuildArray() defined to return an int? If it is supposed to return an int, why have you not included a return statement to make it actually return a value?

Unfortunately, in my opinion, warnings are disable in the Arduino compile and link process, or the compiler would have told you that you have issues with that code.

Your "BuildArray" function does nothing of the sort. The array already exists, as a global array. The function is not building it.

Learning to properly name functions will serve you well in the future. As will learning about scope.

feoIII:
Thanks for the answers, of course the code is a simplified one and i gonna use the function in several places inside the loop.
I want to make a function that returns an array not only a number, i want to call once the function and take two or more data from it. I am an arduino user, my programmming skills are limited so I need an example.
I have remake the code whith yoru help and now it looks like this:

   int * BuildArray()

{static int MyArray[10]={0,1,2,3,4,5,6,7,8,9};
     return MyArray;}

void setup()  
{
int TestArray[10]={0,0,0,0,0,0,0,0,0,0};
 Serial.begin(9600);
   TestArray=BuildArray();
     for (int i=0;i<10;i++)
     {Serial.println (TestArray[i]);}
}
void loop()                    
{}



Now there is no error in "int * BuildArray() ", I dont know what "int * " means, but it still has a bug in:

TestArray=BuildArray();

error: incompatible types in assignment of 'int*' to 'int [10]

thanks for your quick answers.

*Moderator edit:* <mark>[</mark><mark>code</mark><mark>]</mark> ... <mark>[</mark><mark>/code</mark><mark>]</mark> tags added. (Nick Gammon)

The int * refers to a pointer to an object. Do a search for c pointers and arrays for more information. Here is one way your code could be implemented without resorting to the use of dynamic allocation--albeit with a few restrictions.

int * BuildArray (void)
{
    static int MyArray[10]={0,1,2,3,4,5,6,7,8,9};
    return MyArray;
}   

void setup()   
{
  int tmp;
  int *TestArray;
  Serial.begin(9600);
  TestArray = BuildArray();
      for (int i=0;i<10;i++)
       {
         tmp = *(TestArray+i);   // Retrieves the content of the array at index i.  Depending upon compiler may need to be modified to account for elements of different sizes (i.e. ints, longs, etc...)  Look at sizeof function
         Serial.println (tmp);
       }
 }

It is worth learning to work with pointers to objects since they allow C functions to return not just simple data types (bytes, ints, etc...) but more complex ones such as arrays and structs. They are also needed to pass these complex structures to functions

such a nonsense. The OP just won't tell why building an array is needed. It is the key to his answer. How many times do I have to tell a person how to ASK a question? Is this homework?

liudr:
such a nonsense. The OP just won't tell why building an array is needed. It is the key to his answer. How many times do I have to tell a person how to ASK a question? Is this homework?

The OP may (or may) not be working on a homework problem, but they do seem to be asking a specific question that isn't likely to be the entire HW problem. No they didn't explain WHY they want to return an array from a function; never the less, they did form a reasonable question. How to return an array from a function. Clearly they are attempting to learn c programming and formulated there question as well as they could. Indeed I applaud them for first creating an example snippet (as opposed to their full sketch) to demonstrate what they are trying to accomplish.

Of course if they are indeed beginners, there basic approach likely has flaws (such as why they need to return an array defined in a function without dynamic memory allocation), but those are other issues that they will learn about as they experiment.

Here is me pretending to be a newbie:

Hey everyone, I am new here. I have problem here: how do I return array from function?
blah blah

I have seen many explary newbies that actually tell a whole story, or at least after being asked to supply more info, they do this:

Oh yes, I am learning programming. I have played with functions just now and used returning integers but wonder if I can return an array, now that I have seen what an array is. No particular project in mind, just learning the language.

Or maybe, yes this is an assignment. Our teacher said ... and I need some help. (in this case we shouldn't provide fully functional codes, being a teacher myself, I know assignments have purposes and students should do them alone or in assigned groups.)

Nonsense might be too harsh but is it too much to ask why are you asking this very question? We can talor answers to your needs but you need to say it what you need. The question is not specific enough to have one answer and even when the answer is unique, we always try to make suggestions to even the question since beginners don't ask exact questions. Maybe the OP should not return arrays but we never know because he has not told us why.

Hey everyone, I am new here. I have problem here: how do I return array from function?
blah blah

Hi Welcome in Arduinoland, have you searched this thread allready? :wink:

and yes you can pretend anything :wink:

I have a feeling that the OP needs a quick intro to how variables are stored in memory and how values get returned so he could make some sense out of the vague question he asked. Again, as a joke told me, if the OP is not ready to learn that (indicated by lack of information provided regarding why the question), he can't be taught.

The joke goes, a professor showed a student how to do certain thing, later the student still didn't know how to do it and once again the professor showed how to. Only after the third time did the student learn how to. And the professor asked, why didn't you learn the first two times? Student, I wasn't ready the first two times.

Let's not be too eager to teach while the student is not yet ready :wink:

It's been a couple of decades since I was into this stuff, but I don't think that's quite right.

Of course you're referring to arrays which are local variables, and the fact that the array name is syntactically equivalent to pointer-to-array-element. Returning a pointer to a local variable is not safe.

Others have already pointed out that if you have an array which is not allocated on the stack, you can return that just fine. Well, strictly you return the pointer to the array, but it remains valid after the return executes.

IIRC there is [at least] one situation where you can declare a local variable allocated on the stack, and return that safely. If you declare a struct containing an array, you can assign instances of that struct to each other and that structure assignment does a shallow copy of the memory occupied by the struct. If the struct contains an array, the array elements are copied, too. In other words, this is safe:

typedef struct
{
	char text[32];
} Name;

Name getName()
{
	Name result;
	sprintf_s(result.text, sizeof(result.text), "Me");
	return result;
}

I'm not suggesting this is a good design to solve the original problem, but it's a way to return an array.

Assuming you are correct about the shallow copy, you still need to have the array in the caller (for it to be copied into). So you don't achieve anything over passing that other array by reference anyway.

I qualified my answer with the word "really" because you can return arrays, sure:

  • If you don't mind the program crashing
  • If you return a static variable

But the static variable approach has flies on it. Say you return a pointer to this static array (which "lives" inside the function) then you can't afford to call the function twice and expect both variables to be valid. And that's easy enough to do:

char * bar (int i)
  {
  static char buf [10];
  itoa (i, buf, 10);
  return buf;
  }

void setup ()
{
  Serial.begin (115200);
  char foo [50];
  sprintf (foo, "%s %s", bar (1), bar (2));
  Serial.println (foo);
}

void loop () {}

This outputs:

2 2

Which might not be what you expect.

Assuming you are correct about the shallow copy, you still need to have the array in the caller (for it to be copied into). So you don't achieve anything over passing that other array by reference anyway.

I'm thinking along these lines too, however lifetime of temporaries can be extended passed that of the function, eliminating the need to shallow/deep copy.

typedef struct
{
	char text[32];
} Name;

Name getName()
{
	Name result;
	sprintf_s(result.text, sizeof(result.text), "Me");
	return result;
}

void loop()
{
  const Name &n_Name = getName();
  return;
}

By making a constant reference to the return value, its lifetime is extended to that of the reference.

The temporaries are r-value objects, which means that you can't change their values. So the usage of const reference is mandatory. In pre-standard it's was allowed to use non-const references for temporaries but in ISO-C++ it's a compilation error. Changing value of const object could lead to unexpected results.

Using const references to catch the return value of the function could be used as an optimization of avoiding creating temporary objects on function return.

Nick,

That example was tricky, took me some seconds to realize why the "2 2". Good one. I think this discussion ends up becoming a showdown of how deeply everyone understands the language, maybe not what OP wanted to know. Maybe someone should point a function doesn't return any variable, but only returns a value to be assigned to a previously declared variable instead. A variable includes memory location and value stored inside. Even returning pointers was returning the value of a pointer, not the pointer variable in the "return" command.

By making a constant reference to the return value, its lifetime is extended to that of the reference.

Yes but it's getting convoluted. This has the same effect and doesn't use any more memory:

typedef struct
{
    char text[32];
} Name;

void getName(Name & result)
{
    sprintf(result.text, "Me");
}

void loop()
{
  Name n_Name;
  getName(n_Name);
}