How to Return an Array from a Function

Return array in a function

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;
}

How can you return an array from a function in c++

Try to pass the array as a reference instead of returning it.

#include "iostream"

void range(int max, int* ranger){
int n = 0;
while (n < max){
ranger[n] = n;
n += 1;
}

}

int main(){
int ranger[5];
range(5, ranger);
for(int k = 0; k < 5; k++){
std::cout << ranger[k] << " ";
}
return 0;
}

Edit: As @Jarod42 pointed out, I've changed the memory allocation from int * to int[5].

How to return an array from a function?

int* test();

but it would be "more C++" to use vectors:

std::vector< int > test();

EDIT

I'll clarify some point. Since you mentioned C++, I'll go with new[] and delete[] operators, but it's the same with malloc/free.

In the first case, you'll write something like:

int* test() {
return new int[size_needed];
}

but it's not a nice idea because your function's client doesn't really know the size of the array you are returning, although the client can safely deallocate it with a call to delete[].

int* theArray = test();
for (size_t i; i < ???; ++i) { // I don't know what is the array size!
// ...
}
delete[] theArray; // ok.

A better signature would be this one:

int* test(size_t& arraySize) {
array_size = 10;
return new int[array_size];
}

And your client code would now be:

size_t theSize = 0;
int* theArray = test(theSize);
for (size_t i; i < theSize; ++i) { // now I can safely iterate the array
// ...
}
delete[] theArray; // still ok.

Since this is C++, std::vector<T> is a widely-used solution:

std::vector<int> test() {
std::vector<int> vector(10);
return vector;
}

Now you don't have to call delete[], since it will be handled by the object, and you can safely iterate it with:

std::vector<int> v = test();
std::vector<int>::iterator it = v.begin();
for (; it != v.end(); ++it) {
// do your things
}

which is easier and safer.

How do I return an array from a Rust function?

I want to create a function that generates an array of X size with random values.

The type [f64] is a slice, not an array. An array needs a length, like [f64; 25].

Rust's Vec is probably better than a array or slice for this job, unless you're using some sort of foreign function interface (FFI), or a Rust API requires an array (it probably requires Deref<Target = [T]>, basically generic over all array-like types including Vec and arrays). Vec is analogous to C++'s std::vector, and Java's ArrayList.

use rand::prelude::*;

fn generate_vec(len: usize) -> Vec<f64> {
let mut rng = rand::thread_rng();
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
vec.push(rng.gen::<f64>() * 100.);
}
return vec;
}

fn main() {
let generated_vec = generate_vec(10);
println!("{:?}", generated_vec);
}

I made some style changes[1]. If you really want an array, read on.

If you know the size of the array at compile time, you can use an array. If it is too big to fit on the stack, you'll get a stack overflow. Rust 1.51 made this slightly more ergonomic with const generics.

use rand::prelude::*;

fn generate_array<const LEN: usize>() -> [f64; LEN] {
let mut rng = rand::thread_rng();
let mut arr = [0.; LEN];
for item in arr.iter_mut() {
*item = rng.gen::<f64>() * 100.;
}
arr
}

fn main() {
// generate_array can make an array of any length (within stack size limits)
let generated_array1:[f64; 5] = generate_array();
let generated_array2:[f64; 10] = generate_array();
println!("{:?}", generated_array2);
}

If you don't know the length at compile time, or it is too big to fit on the stack, the closest you can get to an array is Box<[T]> (Box of slice of T) using into_boxed_slice().

use rand::prelude::*;

fn generate_array(len: usize) -> Box<[f64]> {
let mut rng = rand::thread_rng();
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
vec.push(rng.gen::<f64>() * 100.);
}
vec.into_boxed_slice()
}

fn main() {
let generated_array = generate_array(10);
println!("{:?}", generated_array);
}

[1] words in function names separated with underscores instead of camelCase, moved println to main() and changed the type of len to usize, since this is how arrays are typically indexed in Rust.

How to return an array in a recursive function?

Mistake here:

int a_size = (sizeof(a)/sizeof(int));

should read

int a_size = l1;

sizeof doesn't measure the size of an array on the heap.

Memory leak here:

return array_global;

should be:

free(a);
free(b);
return array_global;

Returning an array from function in C

… I noticed that the memory of the internal array in my function wasn't deallocated…

Deallocation of memory is not something you can notice or observe, except by looking at the data that records memory reservations (in this case, the stack pointer). When memory is reserved or released, that is just a bookkeeping process about what memory is available or not available. Releasing memory does not necessarily erase memory or immediately reuse it for another purpose. Looking at the memory does not necessarily tell you whether it is in use or not.

When int arr[10] = { 0 }; appears inside a function, it defines an array that is allocated automatically when the function starts executing (or at certain times within the function execution if the definition is in some nested scope). This is commonly done by adjusting the stack pointer. In common systems, programs have a region of memory called the stack, and a stack pointer contains an address that marks the end of the portion of the stack that is currently reserved for use. When a function starts executing, the stack pointer is changed to reserve more memory for that function’s data. When execution of the function ends, the stack pointer is changed to release that memory.

If you keep a pointer to that memory (how you can do that is another matter, discussed below), you will not “notice” or “observe” any change to that memory immediately after the function returns. That is why you see the value of arr_p is the address that arr had, and it is why you see the old data in that memory.

If you call some other function, the stack pointer will be adjusted for the new function, that function will generally use the memory for its own purposes, and then the contents of that memory will have changed. The data you had in arr will be gone. A common example of this that beginners happen across is:

int main(void)
{
int *p = demo(10);
// p points to where arr started, and arr’s data is still there.

printf("arr[3] = %d.\n", p[3]);
// To execute this call, the program loads data from p[3]. Since it has
// not changed, 3 is loaded. This is passed to printf.

// Then printf prints “arr[3] = 3.\n”. In doing this, it uses memory
// on the stack. This changes the data in the memory that p points to.

printf("arr[3] = %d.\n", p[3]);
// When we try the same call again, the program loads data from p[3],
// but it has been changed, so something different is printed. Two
// different things are printed by the same printf statement even
// though there is no visible code changing p[3].
}

Going back to how you can have a copy of a pointer to memory, compilers follow rules that are specified abstractly in the C standard. The C standard defines an abstract lifetime of the array arr in demo and says that lifetime ends when the function returns. It further says the value of a pointer becomes indeterminate when the lifetime of the object it points to ends.

If your compiler is simplistically generating code, as it does when you compile using GCC with -O0 to turn off optimization, it typically keeps the address in p and you will see the behaviors described above. But, if you turn optimization on and compile more complicated programs, the compiler seeks to optimize the code it generates. Instead of mechanically generating assembly code, it tries to find the “best” code that performs the defined behavior of your program. If you use a pointer with indeterminate value or try to access an object whose lifetime has ended, there is no defined behavior of your program, so optimization by the compiler can produce results that are unexpected by new programmers.



Related Topics



Leave a reply



Submit