2

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.

Nick Spot
  • 257
  • 2
  • 4
  • 12
  • 7
    Get a book on C. You won't learn C overnight. – Alexey Frunze Apr 22 '13 at 03:49
  • 2
    google it and it will return a lot of posts from stackoverflow, e.g.,http://stackoverflow.com/questions/3473438/c-return-array-in-a-function – taocp Apr 22 '13 at 03:51
  • Unlike Java there are many ways to return and modify an array in C, You must refer a good book or good guide to know the whole story.. the above mentioned link is a great help though... – AurA Apr 22 '13 at 03:54
  • This is the reason, programming languages must be learnt in a proper order , c->c++->java , not the other way round... – Barath Ravikumar Apr 22 '13 at 03:55
  • @BarathBushan: come on, let's not start language wars here. There are some concepts that are more easily understood in a higher-level language, that are confusing or difficult in C. In any case, this type of question could come up for a newbie to programming in general, though not perhaps in this exact form. – siride Apr 22 '13 at 03:56
  • @BarathBushan: I don't think that the order is so important..IMHO – Jack Apr 22 '13 at 03:56
  • @siride it was just a suggestion of the order to approach abstraction levels or prog lannguages, it need not be true.. – Barath Ravikumar Apr 22 '13 at 04:01
  • @JohnHarrod Welcome to C John.It's not difficult if you are consistent in your effort.A knowledge of Java will only help you appreciate C more.Believe me,many of those who start with C may have initial apprehensions about "difficulty of Java". – Rüppell's Vulture Apr 22 '13 at 04:13
  • Thank you. Yes maybe you are right. But people take it too serious and advize us to read book, and actually this kind of trivial stuff can't be found in any book. Just my opinion. Anyway thank you for all your help, i'v updated with the real problem – Nick Spot Apr 22 '13 at 04:17
  • [You can return array from function in C. Go through this link][1] [1]: http://stackoverflow.com/questions/15353016/c-program-returning-array/15353148#15353148 – Hitesh Menghani Apr 22 '13 at 04:48

5 Answers5

1

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".

user268396
  • 11,576
  • 2
  • 31
  • 26
1

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).

siride
  • 200,666
  • 4
  • 41
  • 62
  • C pointers and C arrays are equivalent for the purpose of considering **what the language allows you to do with them**. In particularly, `arr[0]` dereferences the pointer `*arr` just fine (and vice versa), which is why `&arr[idx]` in combination with a size_t or similar argument is commonly used to modify flat chunks of objects at specific offsets. – user268396 Apr 22 '13 at 03:56
  • @user268396: but it's still important to remind people that they aren't strictly the same. For example, if x is a 10-int array, sizeof(x) is 40 (on x86 Linux), but if x is a pointer to a 10-int array, sizeof(x) is 4. – siride Apr 22 '13 at 04:02
  • yes. thank you. I have updated the question with the real problem. Please take a look – Nick Spot Apr 22 '13 at 04:15
  • Ok. Thank you very much. That was the case. I thought i was messing p with pointers, and could only access the first element. Thank you. – Nick Spot Apr 22 '13 at 04:22
1

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].

kishoredbn
  • 2,007
  • 4
  • 28
  • 47
0
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.

StarPinkER
  • 14,081
  • 7
  • 55
  • 81
  • You can indeed use `5[a]` ... what makes you think you can't? – Jim Balter Apr 22 '13 at 04:22
  • "char *argv[] and char *argv are actually same" -- Wrong. "the compiler will convert the int a[] to int a" -- Wrong. – Jim Balter Apr 22 '13 at 04:26
  • "load the address of p into register" -- not likely, as there's no need to do so. Only the value of p will be loaded. – Jim Balter Apr 22 '13 at 04:28
  • In parameter declarations, `char* argv[]` is the same as `char** argv`; `int a[]` is the same as `int* a`. Also your 7 steps are full of redundancies and things that won't happen. – Jim Balter Apr 22 '13 at 04:32
  • Here's what will actually happen in a common implementation: `p` will already be in a register. The compiler will generate "load p <- [a's address]", "load returnreg <- 4; store returnreg -> 5*4(p)", "return from function". – Jim Balter Apr 22 '13 at 04:35
  • "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" -- not always. 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. – Jim Balter Apr 22 '13 at 04:41
  • Then can you elaborate when will it do this conversion? – StarPinkER Apr 22 '13 at 04:44
  • "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." -- C Standard, 6.3.2.1/3 – Jim Balter Apr 22 '13 at 04:59
  • I'll update this answer based on your remarkable comments, thanks. @JimBalter – StarPinkER Apr 22 '13 at 05:05
  • You still mistakenly claim that "`char *argv[]` and `char *argv` are the same", and ditto for `int a[]` and `int a`. But since array types in parameters are converted to pointer types, correct is `char** argv` and `int* a`. – Jim Balter Apr 22 '13 at 05:19
  • Sorry, that is a mistake, I typed char **argv but SO interpreted it into italic. @JimBalter – StarPinkER Apr 22 '13 at 05:35
0

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;
}
BenMorel
  • 34,448
  • 50
  • 182
  • 322
hustwcw
  • 57
  • 5