292

I have an array int arr[5] that is passed to a function fillarr(int arr[]):

int fillarr(int arr[])
{
    for(...);
    return arr;
}
  1. How can I return that array?
  2. How will I use it, say I returned a pointer how am I going to access it?
apxcode
  • 7,696
  • 7
  • 30
  • 41
Ismail Marmoush
  • 13,140
  • 25
  • 80
  • 114
  • 66
    strictly speaking in this context you don't need to return the array since the array is passed by reference so any changes to elements inside 'arr' will be seen outside the function. – BuggerMe Aug 13 '10 at 02:25
  • 15
    returning the array is convenient for chaining functions. – seand Aug 13 '10 at 02:28
  • 7
    As long as you're not making the mistake of creating an array on the stack and returning a pointer to it. – detly Aug 13 '10 at 02:44
  • 1
    @buggerme yes you're right , but you can consider the array returned arr2 , totally another array , my mistake sry :) – Ismail Marmoush Aug 13 '10 at 02:52
  • 2
    @ismail: It cannot return a new array, unless that array was dynamically allocated. And if that's the case, use `std::vector`. – GManNickG Aug 13 '10 at 03:33
  • 7
    @BuggerMe: Arrays are **not** passed by reference (unless you request it with a much funnier syntax), in the code, the array **decays** into a pointer to the first element and that is passed to the function. The `5` in the function signature is discarded by the compiler. – David Rodríguez - dribeas Aug 13 '10 at 08:20
  • @David in the essence of C, when you pass arrays you always pass them by reference allowing the contents of the array to be changed. What I think you mean is passing the array ptr by reference allowing changing the ptr. – BuggerMe Aug 16 '10 at 02:32
  • 7
    @BuggerMe: Not, not really. I was being precise as I have grown used to people misunderstanding the semantics of the *pass-by-value* syntax for arrays in C++. Passing an array by reference is: `void foo( int (&array)[5] );` (array of 5 ints by reference). When you pass by reference what you get inside the function is a *reference* to the actual type. On the other hand `void foo( int array[5] )` is translated by the compiler to `void foo(int*)` during the function definition. Calling `foo( myarray )` produces the *decay* of the array to a pointer to the first element. – David Rodríguez - dribeas Aug 16 '10 at 07:39
  • @David sorry but a c-array is never passed by value, the only way you can do that (in C) is by putting into a struct. I agree that the pointer to the array is by value but the array itself is passed by value. – BuggerMe Aug 18 '10 at 04:09
  • 3
    @BuggerMe: Maybe I was not clear enough, I *know* that in C/C++, arrays are never actually passed by value. If you carefully read the comment you will see "semantics of the *pass-by-value* syntax". That is, the syntax is the that of *pass-by-value*, but the semantics are not that of *pass-by-value*, the language transforms that *syntax* into the known *decayed array*. This c++ discussion is extending well beyond the intended use of the comments. Google for *array reference decay c++*. One of the first results is [this](http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=241). – David Rodríguez - dribeas Aug 18 '10 at 07:36

21 Answers21

252

In this case, your array variable arr can actually also be treated as a pointer to the beginning of your array's block in memory, by an implicit conversion. This syntax that you're using:

int fillarr(int arr[])

Is kind of just syntactic sugar. You could really replace it with this and it would still work:

int fillarr(int* arr)

So in the same sense, what you want to return from your function is actually a pointer to the first element in the array:

int* fillarr(int arr[])

And you'll still be able to use it just like you would a normal array:

int main()
{
  int y[10];
  int *a = fillarr(y);
  cout << a[0] << endl;
}
GManNickG
  • 494,350
  • 52
  • 494
  • 543
Brent Writes Code
  • 19,075
  • 7
  • 52
  • 56
  • 50
    To clarify, that "classic C++ statement" is false; arrays are not pointers. – GManNickG Aug 13 '10 at 02:24
  • 35
    remember the a[i] == *(a + i) rule – seand Aug 13 '10 at 02:25
  • How should I rephrase it? Isn't the array variable really just a constant pointer to the beginning of the memory block allocated for the array? And then the `[]` just does pointer arithmetic based off of that initial address to locate further elements in the array? – Brent Writes Code Aug 13 '10 at 02:26
  • 9
    @Brent Nash, no. an array is an array. A pointer to the start of the array is a pointer. It just happens that the compiler has some syntactic sugar that does the translation for you in some situations. `array` and `&array` are interchangeable in a lot of cases. – Carl Norum Aug 13 '10 at 02:27
  • 27
    @Brent: No. An array is it's own type, it's not a special kind of pointer. The type of `a` in `int a[10]` is `int[10]`. What you can say is arrays "decay" into pointers to their first element. (This is an implicit array-to-pointer conversion.) Then your answer would go along the lines mine does. If you edit your answer to differentiate between arrays, array-to-pointer conversion, and pointers, I'll delete my answer since they would have the same core information and you were first. – GManNickG Aug 13 '10 at 02:28
  • I'll leave this answer here if for no other reason than I think this comment chain has some really valuable comments. I think @Potatoswatter should probably get your vote for correct answer though. Thanks for the good comments, all. – Brent Writes Code Aug 13 '10 at 02:39
  • 8
    @seand remember the a[i] == *(a + sizeof(a)*i) rule – Amir Mar 18 '16 at 16:34
  • 2
    @Amir, question has C++ tag, in which your expression evaluates to false. – magras Aug 23 '16 at 13:56
  • @BrentNash, your final example here begs the question, "why not just keep using `y` instead of `a`?" I think it would be helpful for you to add that when you modify an array inside of a function--the array having been passed into the function, the modifications are retained outside the function after it returns/exits, therefore, `cout << y[0] << endl;` would print the exact same thing in this case as `cout << a[0] << endl;`, again, because the `y` array was modified in place by the function. – Gabriel Staples Aug 13 '17 at 15:12
  • I just edited the answer to include my comments. I hope that's ok. I think this is important info to make sure people understand. – Gabriel Staples Aug 13 '17 at 15:19
  • Also, I would just use `void fillarr(int arr[])` if it was me writing this, instead of `int* fillarr(int arr[])`. Then, after I fill the array, if I really want a separate pointer variable, I'd use `int* a = y`. This is simpler and more clear than having fillarr return something I think. – Gabriel Staples Aug 13 '17 at 15:25
  • 3
    @Amir There is no such rule. `a[i]` literally means `*(a + i)`; your code is wrong. – melpomene Oct 23 '18 at 04:53
  • 1
    @melpomene yes i am developing c++ now i found that you are right. suggest me to remove my comment or not? – Amir Oct 24 '18 at 19:40
  • @magras I didn't get your comment `question has C++ tag, in which your expression evaluates to false`. How is it wrong in `cpp`? Kindly explain !! Also, what will `sizeof(a)` return in `*(a + sizeof(a)*i)` in @Amir comment? – asn Jan 03 '19 at 18:10
  • @AjaySinghNegi, `sizeof(a)` will return size of pointer type, not the size of element. More than that in C++ pointer arithmetic already accommodates to pointed element size, so his rule could be corrected in two ways: `a[i] == *(a + i)` or if you want to do it manually (and probably trigger UB) `a[i] == *(int*)((char*)a + sizeof(*a) * i)`. Probably there is a difference between plain C and C++, which caused this confusion, but I don't know plain C. – magras Jan 04 '19 at 12:21
  • @magras Why does [this](https://stackoverflow.com/questions/4108313/how-do-i-find-the-length-of-an-array#answer-4108350) gives the size of array, then? I mean, Shouldn't `sizeof(array)` give the total size of the array(`sizeof(int) * total_no_of_elements`)? What is the difference b/w what you are saying and the one I've linked? – asn Jan 04 '19 at 12:35
  • @AjaySinghNegi, there is a difference between array and pointer types. In this answer `a` declared as a pointer: `int *a = fillarr(y);`. In C++ arrays doesn't store their size at run time. So information about size available only at compile time as a type. It isn't very easy to pass array types in and out of functions so, there are more modern ways to achieve the same goal. If you want to keep and work with array size at compile time, it's better to use `std::array`. Or if you want to have runtime sized array you can use `std::vector` specifying size at construct time. – magras Jan 04 '19 at 12:57
  • Late to the discussion but I don't see it here and someone slap me if I'm missing it....what would be the advantage to returning an array or pointer to the array if the array memory location is being updated by the function to begin with? Or maybe there's not one? – Dan Oct 24 '19 at 17:46
136

C++ functions can't return C-style arrays by value. The closest thing is to return a pointer. Furthermore, an array type in the argument list is simply converted to a pointer.

int *fillarr( int arr[] ) { // arr "decays" to type int *
    return arr;
}

You can improve it by using an array references for the argument and return, which prevents the decay:

int ( &fillarr( int (&arr)[5] ) )[5] { // no decay; argument must be size 5
    return arr;
}

With Boost or C++11, pass-by-reference is only optional and the syntax is less mind-bending:

array< int, 5 > &fillarr( array< int, 5 > &arr ) {
    return arr; // "array" being boost::array or std::array
}

The array template simply generates a struct containing a C-style array, so you can apply object-oriented semantics yet retain the array's original simplicity.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • 5
    +1 for giving an example of how an array can be passed by reference. But you are wrong in that you cannot return an array by reference. The simplest syntax to achieve it is by using a typedef: `typedef int array[5]; array& foo();` But you don't even need the typedef if you care to write this: `int (&foo())[5] { static int a[5] = {}; return a; }`, the example in the question would be: `int (&foo( int (&a)[5] ))[5] { return a; }`. Simple, isn't it? – David Rodríguez - dribeas Aug 13 '10 at 08:28
  • @David: thanks, I got the misimpression from the Comeau message `error: function returning array is not allowed` which occurs if you leave out the outer parens in the non-typedef syntax. Fortunately, today I reviewed the right-left rule for another question and managed to construct the right thing… after seeing you say it's possible… before seeing that you gave the code :vP . – Potatoswatter Aug 13 '10 at 09:19
  • 2
    The answer by [chubsdad](http://stackoverflow.com/questions/3473438/c-return-array-in-a-function/3473570#3473570) has the correct quote from the standard: you cannot return an array, but you can return a reference or pointer to an array. Arrays are non-copyable (as a type) and as such they cannot be returned --which would imply a copy-- and when that syntax is present the compiler will convert the argument into a pointer. – David Rodríguez - dribeas Aug 13 '10 at 09:59
  • 3
    @David: So it does. This page is getting to be bizarrely long. Never have so many people voluntarily written so many trivial functions returning an array in one place. – Potatoswatter Aug 13 '10 at 10:25
  • @Potatoswatter I am new to cpp, Can you explain the 2nd code snippet in detail? I am not able to break it into parts for the sake of understanding. – asn Jan 03 '19 at 18:19
  • @AjaySinghNegi It’s the same as `typedef int arri5[5]; arri5 &fillarr( arri5 & arr ) { return arr; }`. Better to use typedef here. – Potatoswatter Jan 04 '19 at 01:04
  • @ilw for example, `foo()[3] = 42;`. – Potatoswatter Mar 03 '19 at 11:38
  • @ilw Just use `auto &&`. – Potatoswatter Mar 03 '19 at 11:40
  • @ilw If you need to express something more specific, then it depends what. In any case, with a C++98 compiler, returning the pointer type is probably more portable, or defensive against compiler bugs. – Potatoswatter Mar 03 '19 at 11:48
  • then why this doesn't work ? `char* sc() { const char v[] = "t1"; return *v; }` . or, maybe thats related to const ? – irvnriir Mar 18 '23 at 18:55
40

In C++11, you can return std::array.

#include <array>
using namespace std;

array<int, 5> fillarr(int arr[])
{
    array<int, 5> arr2;
    for(int i=0; i<5; ++i) {
        arr2[i]=arr[i]*2;
    }
    return arr2;
}
cubuspl42
  • 7,833
  • 4
  • 41
  • 65
25

$8.3.5/8 states-

"Functions shall not have a return type of type array or function, although they may have a return type of type pointer or reference to such things. There shall be no arrays of functions, although there can be arrays of pointers to functions."

int (&fn1(int (&arr)[5]))[5]{     // declare fn1 as returning refernce to array
   return arr;
}

int *fn2(int arr[]){              // declare fn2 as returning pointer to array
   return arr;
}


int main(){
   int buf[5];
   fn1(buf);
   fn2(buf);
}
Chubsdad
  • 24,777
  • 4
  • 73
  • 129
15

the answer may depend a bit on how you plan to use that function. For the simplest answer, lets decide that instead of an array, what you really want is a vector. Vectors are nice because the look for all the world like boring, ordinary values you can store in regular pointers. We'll look at other options and why you want them afterwards:

std::vector<int> fillarr( std::vector<int> arr ) {
    // do something
    return arr;
}

This will do exactly what you expect it to do. The upside is that std::vector takes care of making sure everything is handled cleanly. the downside is that this copies a very large amount of data, if your array is large. In fact it copies every element of the array twice. first it copies the vector so that the function can use it as a parameter. then it copies it again to return it to the caller. If you can handle managing the vector yourself, you can do things quite a bit more easily. (it may copy it a third time if the caller needs to store it in a variable of some sort to do more calculation)

It looks like what you're really trying to do is just populate a collection. if you don't have a specific reason to return a new instance of a collection, then don't. we can do it like this

void fillarr(std::vector<int> &  arr) {
    // modify arr
    // don't return anything
}

this way you get a reference to the array passed to the function, not a private copy of it. any changes you make to the parameter are seen by the caller. You could return a reference to it if you want, but that's not really a great idea, since it sort of implies that you're getting something different from what you passed.

If you really do need a new instance of the collection, but want to avoid having it on the stack (and all the copying that entails), you need to create some kind of contract for how that instance is handled. the easiest way to do that is to use a smart pointer, which keeps the referenced instance around as long as anyone is holding onto it. It goes away cleanly if it goes out of scope. That would look like this.

std::auto_ptr<std::vector<int> > fillarr( const std::vector<int> & arr) {
    std::auto_ptr<std::vector<int> > myArr(new std::vector<int>);
    // do stuff with arr and *myArr
    return myArr;
}

For the most part, using *myArr works identically to using a plain vanilla vector. This example also modifies the parameter list by adding the const keyword. Now you get a reference without copying it, but you can't modify it, so the caller knows it'll be the same as before the function got to it.

All of this is swell, but idiomatic c++ rarely works with collections as a whole. More normally, you will be using iterators over those collections. that would look something more like this

template <class Iterator>
Iterator fillarr(Iterator arrStart, Iterator arrEnd) {
    Iterator arrIter = arrStart;
    for(;arrIter <= arrEnd; arrIter++)
       ;// do something
    return arrStart;
}

Using it looks a bit odd if you're not used to seeing this style.

vector<int> arr;
vector<int>::iterator foo = fillarr(arr.begin(), arr.end());

foo now 'points to' the beginning of the modified arr.

What's really nice about this is that it works equally well on vector as on plain C arrays and many other types of collection, for example

int arr[100];
int *foo = fillarr(arr, arr+100);

Which now looks an awful lot like the plain pointer examples given elsewhere in this question.

SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
11

This:

int fillarr(int arr[])

is actually treated the same as:

int fillarr(int *arr)

Now if you really want to return an array you can change that line to

int * fillarr(int arr[]){
    // do something to arr
    return arr;
}

It's not really returning an array. you're returning a pointer to the start of the array address.

But remember when you pass in the array, you're only passing in a pointer. So when you modify the array data, you're actually modifying the data that the pointer is pointing at. Therefore before you passed in the array, you must realise that you already have on the outside the modified result.

e.g.

int fillarr(int arr[]){
   array[0] = 10;
   array[1] = 5;
}

int main(int argc, char* argv[]){
   int arr[] = { 1,2,3,4,5 };

   // arr[0] == 1
   // arr[1] == 2 etc
   int result = fillarr(arr);
   // arr[0] == 10
   // arr[1] == 5    
   return 0;
}

I suggest you might want to consider putting a length into your fillarr function like this.

int * fillarr(int arr[], int length)

That way you can use length to fill the array to it's length no matter what it is.

To actually use it properly. Do something like this:

int * fillarr(int arr[], int length){
   for (int i = 0; i < length; ++i){
      // arr[i] = ? // do what you want to do here
   }
   return arr;
}

// then where you want to use it.
int arr[5];
int *arr2;

arr2 = fillarr(arr, 5);

// at this point, arr & arr2 are basically the same, just slightly
// different types.  You can cast arr to a (char*) and it'll be the same.

If all you're wanting to do is set the array to some default values, consider using the built in memset function.

something like: memset((int*)&arr, 5, sizeof(int));

While I'm on the topic though. You say you're using C++. Have a look at using stl vectors. Your code is likely to be more robust.

There are lots of tutorials. Here is one that gives you an idea of how to use them. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html

hookenz
  • 36,432
  • 45
  • 177
  • 286
8

This is a fairly old question, but I'm going to put in my 2 cents as there are a lot of answers, but none showing all possible methods in a clear and concise manner (not sure about the concise bit, as this got a bit out of hand. TL;DR ).

I'm assuming that the OP wanted to return the array that was passed in without copying as some means of directly passing this to the caller to be passed to another function to make the code look prettier.

However, to use an array like this is to let it decay into a pointer and have the compiler treat it like an array. This can result in subtle bugs if you pass in an array like, with the function expecting that it will have 5 elements, but your caller actually passes in some other number.

There a few ways you can handle this better. Pass in a std::vector or std::array (not sure if std::array was around in 2010 when the question was asked). You can then pass the object as a reference without any copying/moving of the object.

std::array<int, 5>& fillarr(std::array<int, 5>& arr)
{
    // (before c++11)
    for(auto it = arr.begin(); it != arr.end(); ++it)
    { /* do stuff */ }

    // Note the following are for c++11 and higher.  They will work for all
    // the other examples below except for the stuff after the Edit.

    // (c++11 and up)
    for(auto it = std::begin(arr); it != std::end(arr); ++it)
    { /* do stuff */ }

    // range for loop (c++11 and up)
    for(auto& element : arr)
    { /* do stuff */ }

    return arr;
}

std::vector<int>& fillarr(std::vector<int>& arr)
{
    for(auto it = arr.begin(); it != arr.end(); ++it)
    { /* do stuff */ }
    return arr;
}

However, if you insist on playing with C arrays, then use a template which will keep the information of how many items in the array.

template <size_t N>
int(&fillarr(int(&arr)[N]))[N]
{
    // N is easier and cleaner than specifying sizeof(arr)/sizeof(arr[0])
    for(int* it = arr; it != arr + N; ++it)
    { /* do stuff */ }
    return arr;
}

Except, that looks butt ugly, and super hard to read. I now use something to help with that which wasn't around in 2010, which I also use for function pointers:

template <typename T>
using type_t = T;

template <size_t N>
type_t<int(&)[N]> fillarr(type_t<int(&)[N]> arr)
{
    // N is easier and cleaner than specifying sizeof(arr)/sizeof(arr[0])
    for(int* it = arr; it != arr + N; ++it)
    { /* do stuff */ }
    return arr;
}

This moves the type where one would expect it to be, making this far more readable. Of course, using a template is superfluous if you are not going to use anything but 5 elements, so you can of course hard code it:

type_t<int(&)[5]> fillarr(type_t<int(&)[5]> arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

As I said, my type_t<> trick wouldn't have worked at the time this question was asked. The best you could have hoped for back then was to use a type in a struct:

template<typename T>
struct type
{
  typedef T type;
};

typename type<int(&)[5]>::type fillarr(typename type<int(&)[5]>::type arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

Which starts to look pretty ugly again, but at least is still more readable, though the typename may have been optional back then depending on the compiler, resulting in:

type<int(&)[5]>::type fillarr(type<int(&)[5]>::type arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

And then of course you could have specified a specific type, rather than using my helper.

typedef int(&array5)[5];

array5 fillarr(array5 arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

Back then, the free functions std::begin() and std::end() didn't exist, though could have been easily implemented. This would have allowed iterating over the array in a safer manner as they make sense on a C array, but not a pointer.

As for accessing the array, you could either pass it to another function that takes the same parameter type, or make an alias to it (which wouldn't make much sense as you already have the original in that scope). Accessing a array reference is just like accessing the original array.

void other_function(type_t<int(&)[5]> x) { /* do something else */ }

void fn()
{
    int array[5];
    other_function(fillarr(array));
}

or

void fn()
{
    int array[5];
    auto& array2 = fillarr(array); // alias. But why bother.
    int forth_entry = array[4];
    int forth_entry2 = array2[4]; // same value as forth_entry
}

To summarize, it is best to not allow an array decay into a pointer if you intend to iterate over it. It is just a bad idea as it keeps the compiler from protecting you from shooting yourself in the foot and makes your code harder to read. Always try and help the compiler help you by keeping the types as long as possible unless you have a very good reason not to do so.

Edit

Oh, and for completeness, you can allow it to degrade to a pointer, but this decouples the array from the number of elements it holds. This is done a lot in C/C++ and is usually mitigated by passing the number of elements in the array. However, the compiler can't help you if you make a mistake and pass in the wrong value to the number of elements.

// separate size value
int* fillarr(int* arr, size_t size)
{
    for(int* it = arr; it != arr + size; ++it)
    { /* do stuff */ }
    return arr;
}

Instead of passing the size, you can pass the end pointer, which will point to one past the end of your array. This is useful as it makes for something that is closer to the std algorithms, which take a begin and and end pointer, but what you return is now only something that you must remember.

// separate end pointer
int* fillarr(int* arr, int* end)
{
    for(int* it = arr; it != end; ++it)
    { /* do stuff */ }
    return arr;
}

Alternatively, you can document that this function will only take 5 elements and hope that the user of your function doesn't do anything stupid.

// I document that this function will ONLY take 5 elements and 
// return the same array of 5 elements.  If you pass in anything
// else, may nazal demons exit thine nose!
int* fillarr(int* arr)
{
    for(int* it = arr; it != arr + 5; ++it)
    { /* do stuff */ }
    return arr;
}

Note that the return value has lost it's original type and is degraded to a pointer. Because of this, you are now on your own to ensure that you are not going to overrun the array.

You could pass a std::pair<int*, int*>, which you can use for begin and end and pass that around, but then it really stops looking like an array.

std::pair<int*, int*> fillarr(std::pair<int*, int*> arr)
{
    for(int* it = arr.first; it != arr.second; ++it)
    { /* do stuff */ }
    return arr; // if you change arr, then return the original arr value.
}

void fn()
{
    int array[5];
    auto array2 = fillarr(std::make_pair(&array[0], &array[5]));

    // Can be done, but you have the original array in scope, so why bother.
    int fourth_element = array2.first[4];
}

or

void other_function(std::pair<int*, int*> array)
{
    // Can be done, but you have the original array in scope, so why bother.
    int fourth_element = array2.first[4];
}

void fn()
{
    int array[5];
    other_function(fillarr(std::make_pair(&array[0], &array[5])));
}

Funny enough, this is very similar to how std::initializer_list work (c++11), but they don't work in this context.

Adrian
  • 10,246
  • 4
  • 44
  • 110
5

to return an array from a function , let us define that array in a structure; So it looks something like this

struct Marks{
   int list[5];
}

Now let us create variables of the type structure.

typedef struct Marks marks;
marks marks_list;

We can pass array to a function in the following way and assign value to it:

void setMarks(int marks_array[]){
   for(int i=0;i<sizeof(marks_array)/sizeof(int);i++)
       marks_list.list[i]=marks_array[i];
}

We can also return the array. To return the array , the return type of the function should be of structure type ie marks. This is because in reality we are passing the structure that contains the array. So the final code may look like this.

marks getMarks(){
 return marks_list;
}
Sandeep
  • 106
  • 1
  • 4
3

the Simplest way to do this ,is to return it by reference , even if you don't write the '&' symbol , it is automatically returned by reference

     void fillarr(int arr[5])
  {
       for(...);

  }
nada
  • 31
  • 2
2
int *fillarr(int arr[])

You can still use the result like

int *returned_array = fillarr(some_other_array);
if(returned_array[0] == 3)
    do_important_cool_stuff();
Daniel
  • 1,994
  • 15
  • 36
  • I don't think the 'int [] fillarr ...' is legal. The 'int *fillarr' is what you would use due to array-pointer equivalence. – seand Aug 13 '10 at 02:24
2

As above mentioned paths are correct. But i think if we just return a local array variable of a function sometimes it returns garbage values as its elements.

in-order to avoid that i had to create the array dynamically and proceed. Which is something like this.

int* func()
{
  int* Arr = new int[100];
  return Arr;
}

int main()
{
  int* ArrResult = func();
  cout << ArrResult[0] << " " << ArrResult[1] << endl;
  return 0;
} 




Shehanmark
  • 41
  • 1
  • 6
1

Source: https://www.tutorialspoint.com/cplusplus/cpp_return_arrays_from_functions.htm

C++ does not allow to return an entire array as an argument to a function. However, you can return a pointer to an array by specifying the array's name without an index.

  1. If you want to return a single-dimension array from a function, you would have to declare a function returning a pointer as in the following example:
int * myFunction()    {
   .
   .
   .
}
  1. C++ does not advocate to return the address of a local variable to outside of the function so you would have to define the local variable as static variable.

Applying these rules on the current question, we can write the program as follows:

# include <iostream>

using namespace std;

int * fillarr( );


int main ()
{

   int *p;

   p = fillarr();

   for ( int i = 0; i < 5; i++ )
       cout << "p[" << i << "] : "<< *(p + i) << endl;

    return 0;
}


int * fillarr( )
{
    static int  arr[5];

    for (int i = 0; i < 5; ++i)
        arr[i] = i;

    return arr;
 }

The Output will be:

p[0]=0
p[1]=1
p[2]=2
p[3]=3
p[4]=4
dcmorse
  • 1,011
  • 11
  • 15
MAQ
  • 29
  • 2
0
template<typename T, size_t N>
using ARR_REF = T (&)[N];

template <typename T, size_t N>
ARR_REF<T,N> ArraySizeHelper(ARR_REF<T,N> arr);

#define arraysize(arr) sizeof(ArraySizeHelper(arr))
Nozama
  • 244
  • 4
  • 8
  • 7
    Consider improving your answer. _[Code-only answers may fall under 'Very Low Quality' ...and are candidates for deletion....We've always touted that we aren't a code factory. We are the people who teach others to fish. Code-only answers only feed a person for a day](http://meta.stackexchange.com/questions/148272/is-there-any-benefit-to-allowing-code-only-answers-while-blocking-code-only-ques)_ –  Jul 24 '15 at 04:20
0

and what about:

int (*func())
{
    int *f = new int[10] {1,2,3};

    return f;
}

int fa[10] = { 0 };
auto func2() -> int (*) [10]
{
    return &fa;
}
Alexandr
  • 154
  • 1
  • 7
0

Actually when you pass an array inside a function, the pointer to the original array is passed in the function parameter and thus the changes made to the array inside that function is actually made on the original array.

#include <iostream>

using namespace std;

int* func(int ar[])
{
    for(int i=0;i<100;i++) 
        ar[i]=i;
    int *ptr=ar;
    return ptr;
}


int main() {
    int *p;
    int y[100]={0};    
    p=func(y);

    for(int i=0;i<100;i++) 
        cout<<i<<" : "<<y[i]<<'\n';
}

Run it and you will see the changes

  • 1
    Please use proper english wording (you'll instead of u'll) and omit empty phrases like "buddy". – hellow Sep 12 '18 at 06:15
  • Also: "then actually it is passed as a reference" is wrong. The variable `y` itself is passed as a copy of itself, but because it's a pointer, you will directly operate on the array. Please edit your answer. – hellow Sep 12 '18 at 06:17
  • https://stackoverflow.com/questions/5573310/difference-between-passing-array-and-array-pointer-into-function-in-c TL;DR *"Thus, the two forms are identical."* – hellow Sep 14 '18 at 05:42
  • Yes it is technically an array, you're right, but what is copied is a pointer to the array, not the array itself. – hellow Sep 14 '18 at 05:43
0

And why don't "return" the array as a parameter?

fillarr(int source[], size_t dimSource, int dest[], size_t dimDest)
{

    if (dimSource <= dimDest)
    {
        for (size_t i = 0; i < dimSource; i++)
        {   
            //some stuff...
        }
    }
    else 
    {
        //some stuff..
    }
}

or..in a simpler way (but you have to know the dimensions...):

fillarr(int source[], int dest[])
{
    //...
}
Giovanni Paolin
  • 171
  • 1
  • 3
0

A simple and elaborate example, so that I can refer here if I forget the concept and need help.

#include <iostream>
using namespace std;
int *ReturnArray(int arr[], int size)
{
    static int MinMax[2] = {0, 0}; // must use static, else address would be deleted after the return is reached
    MinMax[0] = arr[0];
    MinMax[1] = arr[size - 1];
    return MinMax;
}
int main()

{
    int arr[] = {1, 2, 3};
    int size = sizeof(arr) / sizeof(*arr);
    int *ans;                     // pointer to hold returned array
    ans = ReturnArray(arr, size); // only pointer can receive the return, not an array
    cout << "Min: " << ans[0] << " Max: " << ans[1];
    return 0;
}
Pawan Kumar
  • 114
  • 9
  • this isn't related to the asker's question. they take an array as an argument. you have a static array in a function. that's really different. you can ask another question for your own purposes. – starball Sep 03 '22 at 07:20
0
int *arr(int size)
{
    int *A;
    A = new int[size];
    for (int i = 0; i < size; i++)
    {
        A[i] = i + 1;
    }
    return A;
}
int main()
{
    int size = 5;
    int *A = arr(size);
    return 0;
}
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](https://stackoverflow.com/help/how-to-answer). – Nol4635 Aug 04 '23 at 23:06
-1

Here's a full example of this kind of problem to solve

#include <bits/stdc++.h>
using namespace std;
int* solve(int brr[],int n)
{
sort(brr,brr+n);
return brr;
}

int main()
{
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++)
{
    cin>>arr[i];
}
int *a=solve(arr,n);
for(int i=0;i<n;i++)
{
    cout<<a[i]<<endl;
}

return 0;
}
Shaonsani
  • 178
  • 8
-1

i used static array so that while returning array it should not throw error as you are returning address of local variable... so now you can send any locally created variable from function by making it as static...as it works as global variable....

#include<iostream>
using namespace std;

char *func(int n)
{
   // char a[26]; /*if we use this then an error will occur because you are 
                        //  returning address of a local variable*/
    static char a[26];
    char temp='A'; 
    for(int i=0;i<n;i++)
    {
     a[i]=temp;temp++;
    }
    return a;
}
int main()
{
    int n=26;
    char *p=func(n);
    for(int i=0;i<n;i++)
     cout<<*(p+i)<<" ";

   //or you can also print like this
  
    for(int i=0;i<n;i++)
     cout<<p[i]<<" ";    

}
-5

Just define a type[ ] as return value, like:

        private string[] functionReturnValueArray(string one, string two)
    {

        string[] x = {one, two};


        x[0] = "a";
        x[1] = "b";

        return x;
    }

. . . function call:

string[] y;
y = functionReturnValueArray(stringOne, stringTwo)
Ricardo Fercher
  • 917
  • 6
  • 10