C Returning an array from a function - c

And having some trouble grasping arrays in C and how to return them via a function. If I do something like this
int main()
{
int num_set[10]={0,1}; //initialize first two elements as 0,1 and rest as 0
int* p=num_set; //assign array to int pointer called p
printf("\n%i",&num_set); //outputs 2686660 on my machine
printf("\n%i",&num_set[0]); //also outputs 2686660
printf("\n%i",p); //also outputs 2686660
printf("\n%i",p[1]);* //outputs 0; the same as num_set[1]
}
It works as expected, but when I try to return an array through another function like the following
int multiply_by_2(int given_number)
{
int num_set[10];
for(int fun_counter=0; fun_counter<10; fun_counter++)
{
num_set[fun_counter] = (given_number*2) ;
}
return num_set; //return int array num_set to caller
}
int main()
{
int* p = multiply_by_2(300) //assign array returned by function to p
for(int main_counter=0; main_counter>10; main_counter++)
{
printf("\np[%i] = %i"
, i, p[i]);
}
}
I get an error saying "invalid conversion from 'int' to 'int*'"
They was no error when I assigned the array to an int pointer in the first code, but I get this error when I try to return it through a function.
Please help.

In C you cannot return array by value. You would have to return the pointer of the array you want to return.
Pass a pointer and a size for a buffer to store your results.

There are a number of errors here.
The return type of the function multiply_by_2 needs to be int* - i.e a pointer to an integer. What is actually returned is a pointer to the first element of the array.
You are attempting to return a variable initialized on the stack (num_set). This will
disappear as soon as the multiply_by_two function exits, because it is an automatic variable. Instead, you should use the malloc function to allocate heap memory. Here's a link explaining the difference between stack and heap memory
You have a > where you should have a < in the for loop in main. As written the loop will immediately exit.
Minor point - the number 10 is repeated several times throughout the code. It is better practice to use a variable or a #define to give the number a meaningful name
Here's an amended version of the code:
#include <stdio.h>
#include <stdlib.h> //This is required to use malloc
#define ARRAY_SIZE 10
int* multiply_by_2(int given_number)
{
int *num_set =malloc(sizeof(int)*ARRAY_SIZE);
for(int fun_counter=0; fun_counter<ARRAY_SIZE; fun_counter++)
{
num_set[fun_counter] = (given_number*2) ;
}
return num_set; //return int array num_set to caller
}
int main()
{
int* p = multiply_by_2(300); //assign array returned by function to p
for(int i=0; i<ARRAY_SIZE; i++)
{
printf("\np[%i] = %i", i, p[i]);
}
free(p);
}

This is wrong on so many levels, but the compiler error comes from your declaration of "multiply_by_2". You declare it to return an integer, but then you try to return a pointer.

Let's try something like this:
int* multiply_by_2(int size, int given_number)
{
int *ip = (int*)malloc(size*sizeof(int)); // dynamically create int x[size]
for(int fun_counter=0; fun_counter < size; fun_counter++)
{
ip[fun_counter] = (given_number*2) ;
}
return ip; //return int array num_set to caller
}
Caller must free() returned memory.
int main(int argc, char **argv) {
int *ip = multiply_by_2(3, 2);
// ip points to array {4, 4, 4}
free(ip);
return 0;
}
We say that the function caller becomes owner of returned memory, that's why you are responsible to call free() later.

int multiply_by_2(int given_number) // not returning an array, but just an int
The return type of your function is int therefore you will get an error when trying to assign it to int *. Change it to the following:
int* multiply_by_2(int given_number)
This change is acceptable because in C, an array of ints is interchangeable with a pointer to an int.

Your header is wrong. Should be
int* multiply_by_2(int given_number)
You need to return pointer of int, not just int.
Another thing, in the function multiply_by_2 you have created local array. That means that the array will be deleted after the function will end.
You must use dynamic allocation (malloc and free).

Three major problems in your program:
The return type of function is int but you are returning an int * type.
You are returning the pointer to an automatic local variable.
Second expression in for loop in main would not let the body of loop to execute.
Change return type of the function to int * and use dynamic allocation.
int* multiply_by_2(int given_number)
{
int* num_set = malloc(sizeof(int)*10);
// rest of you code
}
And finally change second expression in your for loop in main to main_counter < 10. Use free in main to free the allocated memory.

Related

Where is the error in this function to print a random array?

I don't understand where the error is in the function.I need to print 2 arrays with random elements.
int *boo3(int *x , int n){
x = (int*) malloc(sizeof(int)*n);
int i;
for(i=0;i<n;i++){
x[i] = rand()%10-(rand()%10);;
printf("%5d ",x[i]);
}
printf("\n");
}
int main(int argc, char *argv[])
{
int *x ,*y;
int n , m;
int i,j;
printf("enter size of X[n]: ");
scanf("%d",&n);
printf("enter size of Y[m]: ");
scanf("%d",&m);
x=boo3(*x,n);
y=boo3(*y,m);
free(x);
free(y);
return 0;
}
There are several problems with this code:
x = (int*) malloc(sizeof(int)*n); overwrites the function parameter x.
No return statement in boo3,
x=boo3(*x,m) in this line, *x is dereferencing pointer x which gives you int
In main function, you tried to free uninitialized pointer x and y
In your code
int *boo3(int *x , int n)
This indicates that you should receive a return value from this function.
In general a return value can be error code or any data which you might want to use going ahead.
Just like a math function for addition, taking operands as an argument and returning the sum. In your case, it is a pointer to the memory you have been allocated with.
In boo3() function, you are allocating some memory and you need the pointer to that memory for further usage. boo3() doesn't return anything, however, in main() function, you are assuming that you have caught it, hence the problem.
You should return the pointer to data from boo3().
I can see in main() function,
x=boo3(*x,n);
This is alarming. You are dereferencing a int* pointer and passing an int (instead of int*) as an argument to boo3() function which expects a int*.
If you wish to assign the pointer declared in main() with the address of memory allocated in boo3(), then you don't catch it and change to
boo3(x, n);
boo3(y, m);
And change to
void boo3(int *x , int n)
However, ideally, the function should return and the value be caught as a return value. In that case, change to
int* boo3(int n)
At the end of boo3 add a return x;. And use it as
x = boo3(n);
Additionally, you are not checking if the malloc() has allocated any memory or not. You should check if the pointer is NULL to see if memory is allocated. It is minimum error-checking and handling you need to have. Secondly, malloc() returns a void*, so the typecast is needless.
The problem is, you do not return anything from the function boo3(), and try to use the return value. This causes undefined behavior.
You need to add a return x; at the end of the function so as to return the pointer holding the address of the allocated memory (and populated values).
That said, passing the pointer argument is not needed when you return the pointer from the function. Apart from the fact that your call does not even try to pass a pointer as the first argument, as expected by the function signature - to allocate memory to a pointer from a called function, you need to pass the address of the pointer anyways, passing the pointer alone will not suffice. You don't need to do that, just define the function as
int *boo3(int n) { //......
and in the end, add
return x;
and from main(), call it like
x=boo3(n);
y=boo3(m);
There are many issues in your code.
Following has been corrected:
boo3 now simply returns the pointer to the allocated memory filled with random numbers, the useless x parameter has been removed and the function now contains the missing return statement. This is actually the main problem in your code.
The pointless (int*) cast has been removed from malloc.
The code is formatted properly.
Variables are declared as close as possible to their scope. This is the idiomatic way, declaring all variables at the start of the scope is a thing from the last century.
Usage of meaningful variable names.
This is a correct version of your program:
#include <stdlib.h>
#include <stdio.h>
int* boo3(int n) {
int *array = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
array[i] = rand() % 10 - (rand() % 10);;
printf("%5d ", array[i]);
}
printf("\n");
return array;
}
int main(int argc, char* argv[])
{
int sizex, sizey;
printf("enter size of X[n]: ");
scanf("%d", &sizex);
printf("enter size of Y[m]: ");
scanf("%d", &sizey);
int *xvalues = boo3(sizex);
int *yvalues = boo3(sizey);
free(xvalues);
free(yvalues);
return 0;
}
Disclaimer: for brevity there is no error checking for scanf and malloc.

Retrieve values from arrays in different functions

I'm trying to write a program in c where the length of an array is declared in the main function, then a function is called and allocates the memory and initalizes the values, and then the main function prints the values. I have declared the array and its length globally, but when the main function "retrieves" values from the array, I get a segfault, which, I assume, is because only the pointer on the array is global, but not the values themselves. Is there any method of solving this besides merging the functions?
I'm trying to write a program in c where the length of an array is declared in the main function, then a function is called and allocates the memory and initalizes the values, and then the main function prints the values.
#include <stdio.h>
#include <stdlib.h>
int *foo(size_t len) {
int *values = calloc(len, sizeof *values);
if (values) {
values[2] = 42;
}
return values;
}
int main(void) {
size_t len = 5; // length of array declared in main()
int *p = foo(len); // foo() allocates and initializes
for (int k = 0; k < len; k++) printf("%d: %d\n", k, p[k]); // main() prints the values
free(p);
return 0;
}
I have declared the array and its length globally, but when the main function "retrieves" values from the array, I get a segfault, which, I assume, is because only the pointer on the array is global, but not the values themselves.
Try to avoid globals.
Do not confuse arrays and pointers. See section 6 of the c-faq.
Is there any method of solving this besides merging the functions?
Yes.

C language Array modification with Malloc

void helperWithoutMalloc(int *arr) {
arr[0] = 18;
arr[1] = 21;
arr[2] = 23;
}
int main() {
int *data;
helperWithoutMalloc(data);
printf("%d\n", data[0]);
return 0;
}
The above method successfully modify the value of data through the method helperWithoutMalloc(); however, when malloc method is applied; similar way doesn't work. Three value in the data array still zero
void helperNotWorking(int *arr) {
arr = malloc(sizeof(int)*3);
arr[0] = 18;
arr[1] = 21;
arr[2] = 23;
}
int main() {
int *data;
helperNotWorking(data);
printf("%d\n", data[0]);
return 0;
}
I'm just wondering what happen when the line arr = malloc(sizeof(int)*3) is implemented; and makes two code so different?
The main confusion is that : first code regardless of its incorrectness, can still modify the array element while second code, can't modify the array elements; since both functions pass the address of array; and we manipulate the array element through address
Any data structure in C as in any other language must be provided with a memory region where it data could be kept. In your first example you failed to do so. The 'data' pointer does not point to any memory and is initialized. It worked by a chance and you just caused your program to write data somewhere, which happened to be writable. you needed something like the following:
int main() {
int data[3]; // allocate an array for data
helperWithoutMalloc(data);
In the above example the memory was provided by the C array of 3 elements.
In a similar fashion you can use malloc:
int main() {
int *data = malloc(sizeof(int) * 3);
helperWithoutMalloc(data);
Note that the space for data was allocated before calling to the function and passed to it. The function can use pointer (memory address) to access the array elements.
In your second example you did a different mistake. You allocated the space, but you assigned the pointer to the parameter of the function. The pointer in your case was passed to your function by value, therefore it is uni-directional. you can pass it to the function but not backwards. It worked perfectly well inside the function but it did not update 'data', so you cannot access the values after returning from the function. There are few ways to work around it. I.e. you can return your pointer from the function:
int *helper() {
int *arr = malloc(sizeof(int)*3);
...
return arr;
}
int main() {
int *data = helper();
...
or you can use a pointer to pointer to pass to the function:
void helper(int **arr) {
*arr = malloc(...)
(*arr)[0] = 0;
...
}
int main () {
int *data;
helper(&data);
In my opinion, the correct way should be
void NoMalloc(int *arr) {
arr[0] = 18;
arr[1] = 21;
arr[2] = 23;
}
int main() {
int *data = (int *)malloc(sizeof(int) * 3);;
NoMalloc(data);
printf("%d\n", data[0]);
free(data);
return 0;
}
The malloc function allocates some memory and returns a pointer to that allocated memory.
Pointer stores addresses in the memory, and when you define a uninitialized pointer (such as the your first piece of code, int * data;) you don't know where the pointer (data) is pointing and therefore accessing the values stored at the location would often cause Access Violations and should never be used.
As with any other type of C variables, pointers are passed by values when serving as an argument of a function. So data itself would not be modified after calling helperWithoutMalloc or helperNotWorking. The second piece of code does not work because after calling helperNotWorking, the data pointer is still an uninitialized pointer. The numbers you though you have stored in data is actually stored in the modified value of arr in the helperNotWorking function, which does not affect does not point to the same address as data anymore.

What is the type of my array? [duplicate]

This question already has answers here:
Return a 2d array from a function
(10 answers)
How to return matrix (2D array) from function? (C)
(3 answers)
Closed 8 years ago.
I have the following function :
int** myfunc() {
int array[2][2];
// operation on the array
return array;
}
And the following error from the compiler :
cannot convert 'int (*)[2]' to 'int**' in return
So my question is : how can I return my array ?
So my question is : how can I return my array ?
You cannot. The array named array has function scope and goes out of scope when the function myfunc returns. This means the array no longer exists and trying to access it will invoke undefined behaviour. Also, the return type of myfunc is int **. In the return statement
return array;
the array named array is implicitly converted to a pointer to its element. int array[2][2]; defines array to be an array of 2 elements of type int[2], i.e., an array of 2 integers. Therefore, array in the return statement is implicitly converted to type int (*)[2], i.e., a pointer to an array of 2 integers. This explains the error message.
If you want to return an array from a function, you should allocate it dynamically using malloc which should later be freed in the caller after its use.
// you should change function signature to take the array size.
// and change return type to (int *) to return a pointer to the
// first element of the dynamically allocated array
int *myfunc(int len) {
int *array = malloc(len * sizeof *array);
if(array == NULL) {
printf("error in memory allocation\n");
return NULL;
// handle it
}
// operation on the array
return array;
}
Please note that an array type object is a contiguously allocated nonempty set of objects with a particular member object type, called the element type. Therefore, a 2-D array is not a new type. It's just an array type where the elements of the array are themselves arrays. This mean we have the following equivalence -
// an automatic array of 200 elements allocated on the stack
int auto_array[10][20];
// a dynamic array of 200 elements allocated on the heap
int *dynamic_array = malloc((10 * 20) * sizeof *array);
printf("%d\n", auto_array[4][8];) // prints element in the 5th row, 9th column
printf("%d\n", dynamic_array[4*10 + 8]); // prints element in the 5th row, 9th column
This only fixes the compiler error
The compiler is already giving you the correct type to return, you just need to give the type a name to return it easily:
typedef int (*myArrayPtr)[2];
myArrayPtr myFunc() {
int foo[2][2];
return foo; //Compiles, BUT DON'T USE IT (see below)
}
Alternatively, you can write the function declaration like this (but please don't, this should only be done in code that tries to win the International Obfuscated C Code Contest):
int (*myFunc())[2] {
int foo[2][2];
return foo; //Compiles, BUT DON'T USE IT (see below)
}
This approach actually works
The code above returns a pointer to a local variable, which is automatically deallocated when myFunc() returns. If the calling function uses the returned pointer in any way, anything might happen. To return a 2D array correctly, you need to malloc() it:
typedef int myArray[2];
myArray* myFunc() {
myArray* foo = malloc(2*sizeof(*foo));
foo[1][1] = 7;
return foo;
}
Note, that one of the two dimensions is encoded in the array type, while the other one is implicit in the pointer. That is why the sizeof of *foo must be multiplied by the size of the first dimension. Of course, you can also encode both dimensions in the array type, but that requires you to write an additional dereference when you access its elements:
typedef int myArray[2][2];
myArray* myFunc() {
myArray* foo = malloc(sizeof(*foo));
(*foo)[1][1] = 7;
return foo;
}
Arrays and pointers, while deceptively similar, are not the same thing in C.
You're trying to return a local variable, memory for which is allocated on the stack. The local variable will be popped off the stack as soon as your function exits, which is why most compilers give you a warning when you try to return the address of a local variable. The returned address points to a value that is gone.
What you need to do, is declare an int** & return it. You can allocate memory dynamically using malloc() present in the malloc.h header. Something like the following should work.
#include <stdio.h>
#include <malloc.h>
int** myfunc()
{
// Allocate memory so array can hold two int *
int** array = malloc(sizeof(int *) * 2);
// Allocate memory for each of the pointers that the array holds
// We want to reserve space for two integers in each slot.
array[0] = malloc(sizeof(int) * 2);
array[1] = malloc(sizeof(int) * 2);
array[0][0] = 0;
array[0][1] = 1;
array[1][0] = 2;
array[1][1] = 3;
return array;
}
int main(void)
{
int i, j;
int **x;
x = myfunc();
for (i = 0; i < 2; ++i) {
for (j = 0; j < 2; ++j) {
printf("%d", x[i][j]);
}
}
return 0;
}
Don't forget to free() the contents of the array when you're done with it.
Arrays are not first-class data types in C, you cannot return an array by copy, and returning a reference to a local variable will have undefined behaviour (and is never good).
There are three ways (at least) to do what you are attempting. The most usual (not to mention safe and efficient) is to have the caller own the array, then pass the array into the function by reference and have the function operate on the provided array:
void myFunc( int array[2][2] )
{
// operate directly on caller's array
}
The second method is to wrap the array in a struct, which is a first-class data type and can be exchanged by copy or reference. Note for large structures, exchange by copy can become expensive computationally.
typedef struct
{
int array[2][2] ;
} array_container ;
array_container myFunc()
{
array_container contained_array ;
return contained_array ;
}
Dynamically allocating the array within the function is a possibility, but leaves the question of who is responsible for freeing the memory and how and when it is safe to do so. However although I would not recommend it:
#define ARRAY_DIM1 2
#define ARRAY_DIM2 2
int** myfunc()
{
int** array = malloc( sizeof(int*) * ARRAY_DIM1 ) ;
int* array_memory = malloc( sizeof(int) * ARRAY_DIM1 * ARRAY_DIM2 ) ;
int i = 0 ;
for( i = 0; i < ARRAY_DIM1; i++ )
{
array[i] = array_memory[i * ARRAY_DIM2]
}
return array;
}

assign dynamic array in a function and send it back to the caller in C

I have been using java for long time but for some reason I need to use C (ANSI C not C++) to write a simple code. I need to pass the pointer from outside to a function, allocate some memory to the pointer and assign some values also before the function return. I have my code like
#include <stdio.h>
#include <stdlib.h>
void test(int *a)
{
int n=3;
// I have to call another function t determine the size of the array
n = estimatesize(); // n >=3
// I tried fix size n=10 also
a = (int*)malloc(n*sizeof(int));
a[0] = 1;
a[1] = 2;
a[2] = 3;
}
void main(void)
{
int *s=NULL;
test(s);
printf("%d %d %d", s[0], s[1], s[2]);
}
I don't know why the code crashes. I thought at the beginning it is estimatesize() return wrong number but even I fix n to 10, the error still there. So I cannot pass a pointer to a function for memory allocation? If so, how can I dynamically create memory inside a function and pass it out? I know it may be a safe problem in this way but I just want to know if it is possible and how to do that. Thanks.
There are two solutions to this: Either return the pointer from the function, or pass the argument by reference.
For the first one, you simply don't take any arguments, instead you return the pointer:
int *test(void)
{
int *a = malloc(...);
...
return a;
}
int main(void)
{
int *s = test();
...
}
For the second one, you need to pass the address of the pointer, in other words a pointer to the pointer, using the address-of operator &:
void test(int **a)
{
*a = malloc(sizeof(int) * 3);
for (int i = 0; i < 3; ++i)
(*a)[i] = i;
}
int main(void)
{
int *s;
test(&s);
...
}
The reason it doesn't work now, is because the pointer (s in main) is passed by copying it. So the function test have a local copy, whose scope is only in the test function. Any changes to a in the test function will be lost once the function returns. And as s is copied for the argument, that means that s in main never actually changes value, it's still NULL after the function call.

Resources