Returning an array using C
You can't return arrays from functions in C. You also can't (shouldn't) do this:
char *returnArray(char array []){
char returned [10];
//methods to pull values from array, interpret them, and then create new array
return &(returned[0]); //is this correct?
}
returned
is created with automatic storage duration and references to it will become invalid once it leaves its declaring scope, i.e., when the function returns.
You will need to dynamically allocate the memory inside of the function or fill a preallocated buffer provided by the caller.
Option 1:
dynamically allocate the memory inside of the function (caller responsible for deallocating ret
)
char *foo(int count) {
char *ret = malloc(count);
if(!ret)
return NULL;
for(int i = 0; i < count; ++i)
ret[i] = i;
return ret;
}
Call it like so:
int main() {
char *p = foo(10);
if(p) {
// do stuff with p
free(p);
}
return 0;
}
Option 2:
fill a preallocated buffer provided by the caller (caller allocates buf
and passes to the function)
void foo(char *buf, int count) {
for(int i = 0; i < count; ++i)
buf[i] = i;
}
And call it like so:
int main() {
char arr[10] = {0};
foo(arr, 10);
// No need to deallocate because we allocated
// arr with automatic storage duration.
// If we had dynamically allocated it
// (i.e. malloc or some variant) then we
// would need to call free(arr)
}
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.
Passing an array as an argument to a function in C
When passing an array as a parameter, this
void arraytest(int a[])
means exactly the same as
void arraytest(int *a)
so you are modifying the values in main.
For historical reasons, arrays are not first class citizens and cannot be passed by value.
Return char[]/string from a function
Notice you're not dynamically allocating the variable, which pretty much means the data inside str
, in your function, will be lost by the end of the function.
You should have:
char * createStr() {
char char1= 'm';
char char2= 'y';
char *str = malloc(3);
str[0] = char1;
str[1] = char2;
str[2] = '\0';
return str;
}
Then, when you call the function, the type of the variable that will receive the data must match that of the function return. So, you should have:
char *returned_str = createStr();
It worths mentioning that the returned value must be freed to prevent memory leaks.
char *returned_str = createStr();
//doSomething
...
free(returned_str);
Passing an array as a function parameter in JavaScript
const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);
See MDN docs for Function.prototype.apply()
.
If the environment supports ECMAScript 6, you can use a spread argument instead:
call_me(...args);
Related Topics
Troubleshooting "Unexpected T_Echo" in Ternary Operator Statement
Php, Why Do You Escape My Quotes
Prepared Parameterized Query with Pdo
Asynchronous Http Requests in PHP
Getting Data from Post Array in Codeigniter
How to Sort a Multidimensional Array by Multiple Columns
Fetch' in Pdo Gets Only One Result
In PHP, How to Generate a Big Pseudo-Random Number
Show Name Instead of Id from Different Table
Dates Not Casting After Upgrading to Laravel 7
How to 'JSON_Encode()' Keys from PHP Array
Ignoring Errors in File_Get_Contents Http Wrapper
How to Get the Current PHP Executable from Within a Script
PHP Upload Size and Its Impact on Post Size and Memory Limit
Multidimensional Array Difference PHP
Check If Http Request Comes from My Android App
What Is the Easiest Way to Use the Head Command of Http in PHP
Warning: MySQL_Num_Rows() Expects Parameter 1 to Be Resource, Boolean Given