Nick Spot
Nick Spot

Reputation: 267

C returning array in function

Im relatively knew to C, i am used to program in Java so i find C a little bit difficult in what concerns arrays. I still cofuse myself with this cases:

int a [];
int* a;
int *a;

In java, i would do something like this to return an array in a function:

int [] returnArr(int [] a){
... modify a ...
return a;
}

int [] a = {...};
int [] b = returnArr(a); ##

How can i do the same in C, specially the parts with ##.

EDITED: I have this function:

float *normalizeValues(float *v, float maxY){

    int size = sizeof(v) / sizeof(float);
    float max = findMax(v);
    float ratio = maxY / max;
    int i;
    for(i = 0; i < size ; ++i){
        v[i] = v[i] * ratio;
    }
    return v;
}

And im doing the following:

float vert [] = {306, 319, 360, 357, 375, 374, 387, 391, 391, 70, 82, 94, 91, 108, 114, 125, 127, 131};
int i = 0;
float *vert2;
vert2 = normalizeValues(vert, 0.7);

for(i = 0; i < sizeof(vert2) / sizeof(float); ++i){
    fprintf(stdout,": %f\n",vert2[i]);
}

And the output is only 1 element.

Upvotes: 2

Views: 439

Answers (5)

hustwcw
hustwcw

Reputation: 57

In C, you can only return a pointer of an array in a function. For example, if you want to return a string(array of char) in a function, you can return a pointer to a null-ended string. If you want to return an array of some other type(int, user-defined struct, etc), you can alloc some memory to store the array, and return the pointer of the array, return the size of the array in the parameter. example:

int *function(int *size)
{
    *size = 10;
    int *intP = (int *)malloc((*size)*sizeof(int));

    return intP;
}

Upvotes: 0

StarPinkER
StarPinkER

Reputation: 14271

int* returnArr(int a[]){
    //modify a
    return a;
}

One need mention is when you use an array in the parameter list of a function, it will be converted into a pointer. So in main(...)'s declaration, char *argv[] and char **argv are actually same. In this case, int a[] and int* a are same. But array and pointer is not the same thing.

Take the following code as an example:

int a[10];
int main(){
    int *p = a;
    p[5] = 4;
    return p[5];
}

p is a pointer, when we access p[i], note that the address of p is not the address of a, the content of p is the address of a. Then the code will:

  1. access the memory to get the content of p, i.e. the address of a.
  2. compute the offset based on i and type of the pointer(int).
  3. access the memory to get the result.

a is an array of int, if we access a[i], the address of a is just the address of a[0], the code will:

  1. Compute the offset based on i and the type int.
  2. Access the memory.

Pointer and array are different types. So if you declare int *p in one file and use it in that file, but define the p as an array in another file, that will cause problem.

You may also wonder about int *p = a, in ANSI, if you use an array(its name) as an expression, the compiler will convert it into a pointer, pointing to the very first element of the array.

Update based on Jim Balter's comments:

If you use an array(its name) as an expression, the compiler will not always convert it into a pointer, pointing to the very first element of the array. For instance, in sizeof(p->q->a), p->q->a is an expression but if a is an array it isn't converted into a pointer.

"Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object.

Upvotes: 0

kishoredbn
kishoredbn

Reputation: 2097

Hope this helps

  #include<stdio.h>

    void change(int *c)/*Pointer c now has the first location of the array a[]*/
    {
      *(c+0) = 0;/*assign values to the array by adding step-size to the first array position*/
      *(c+1) = 1;
      *(c+2) = 2;
      *(c+3) = 3;
      *(c+4) = 4;
    }

    main()
    {
      int a[5]={10,20,30,40,50}; /* Declare and Assign an array a[] of size 5.*/
      int *b = a; /*Declare and assign a Pointer to the location of the array.*/
      change(b); /*pass the pointer(which is now pointing to first position of array) to the change() function.*/
      printf("%d,%d,%d,%d,%d,",a[0],a[1],a[2],a[3],a[4]);/*Print the changed value.*/
    }

Output: 0,1,2,3,4,

From Java point of view, Pointers are simply like(not exactly) Object references.

Object O;

O = New SomeClassName();

Like Object Reference O is pointing to some Actual Object of type SomeClassName, so does pointers in C:

int *b;
b = &a;

Variable b is simply pointing to the address location to a. Taking a deep dive into array concepts:

int a[5];
int *b = a;

Here we are just saying like Mr.*b point to the first location of group a i.e. a[0].

Now the power pointer in C is that from now on, here after:

*b means a[0]
*(b+1) means a[1]
*(b+2) means a[2]
*(b+3) means a[3]
*(b+4) means a[4]

This means you change in *(b+4), you're changing a[4].

Upvotes: 1

siride
siride

Reputation: 209935

EDIT: To directly answer your updated question: you have to pass in the size of the array. C has no mechanism to store the size of arrays like Java does. If the compiler knows about the size of the array because the array is a global or local variable, not dynamically allocated, then you can use the sizeof() operator. Otherwise, you have to know the size separately, or use sentinel values in your array (such as a 0.0 at the end, or a NULL).

As for arrays, pointers and arguments in general, see below:

You will be returning a pointer to the array, which is indicated with the '*' syntax:

int *returnArr(int[] a) {
    // modify a...
    return a;
}

int a[] = { ... };
int *b;
b = returnArr(a);

A few things to note:

  • You can't do assignments in variable declarations that involve non-constant expressions (e.g., function calls). This might have changed in C99, though.
  • The brackets go after the variable name, unlike in Java where they are part of the type. Even though Java's syntax is more consistent, it doesn't quite make sense in C where you often give the array size in the brackets in the variable declaration:

    int a[3] = { ... };

  • There's no way to specify that a function returns an array as opposed to a plain pointer. In C, array references decay to pointers (though pointers and arrays are NOT the same thing, as is commonly claimed). That means that whenever you pass an array around, C only provides a means to a pass a pointer to the array. The whole array isn't actually copied. As it happens, the name of the array is also a pointer to the first element of the array.

Please also take note of what user268396 says in their answer. If you are planning to create a new array and return it, you'll need to either allocate the array dynamically, or have a pointer to an already allocated array be passed in (which is what it seems like you are kind of doing anyway).

Upvotes: 1

user268396
user268396

Reputation: 12006

You can't. When the function returns the stack frame will be wiped out (typically) and your generated array will be clobbered by that. You can however edit the function prototype to accept a pointer to the array to modify. That kind of function argument is known as an "output parameter". Example:

void function func(int a, int b, int[2] to_modify)
{
  to_modify[0] = a;
  to_modify[1] = b;
}
int main()
{
   int foo[2];
   func(1, 2, foo);
   printf("Result: foo[0] = %d, foo[1] = %d\n", foo[0], foo[1]);
   return 0; 
}

This will print "Result: foo[0] = 1, foo[1] = 2".

Upvotes: 1

Related Questions