0

I am new to C development and I am having an issue setting an arrays values in a function and returning to the calling method. The function itself has to return an int and the array size needs to be dynamic, so I am trying to update the original array utilising a pointer to the array. My code is as below:

int getArray(TestType *testArray)
{

    testArray = malloc(2 * sizeof(TestType));
    testArray[0].id = 1;
    testArray[0].testFloat = 1.5;
    testArray[1].id = 2;
    testArray[1].testFloat = 2.5;

    printf("getArray element 2 id = %d\n", testArray[1].id);

    return 1;
}

void main()
{
   TestType *testArray; 
   int i = getArray(*&testArray);   
   printf("main element 2 id = %d\n", testArray[1].id); 
}

When I run this I get the following results:

getArray element 2 id = 2
main element 2 id = 0

I have looked elsewhere and although c returning an array from a function describes a similar issue this is dealing with a char array, whilst I have a user defined struct, so don't believe I can apply the same solution.

Community
  • 1
  • 1
trebor74
  • 133
  • 1
  • 10
  • 1
    C11 draft standard n1570: *6.5.2.2 Function calls 4 An argument may be an expression of any complete object type. In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument. 93) A function may change the values of its parameters, but these changes cannot affect the values of the arguments.* – EOF Aug 10 '16 at 14:19
  • 1
    @EOF absolutely right, just my two cents, for someone who says `I am new to C development`, _only_ those are pretty heavy words. :) – Sourav Ghosh Aug 10 '16 at 14:25
  • 1
    @SouravGhosh: I find that there really is no alternative to reading the standard if you want to *actually understand what is going on* in C. Much of the standard is quite readable as well. – EOF Aug 10 '16 at 14:27
  • @EOF I certainly don't completely disagree, but IMHO, to _start with_ reading the standard, is too much to ask for. :) – Sourav Ghosh Aug 10 '16 at 14:28
  • 1
    @SouravGhosh: Which is why I like to cite relevant parts of the standard. That way, interested people can quickly find the section and find an entry into the subject. It's how I got into it as well. – EOF Aug 10 '16 at 14:29
  • @EOF well, most of us here will have the same story, I believe :) – Sourav Ghosh Aug 10 '16 at 14:30
  • C has neither _methods_ nor _references_. – too honest for this site Aug 10 '16 at 14:34
  • @SouravGhosh: I'm not so sure. Of course it is hard stuff to start with, but then it is well structured. One just has to invest more to start with it, but later it is easier than searching is some C book which splits the information across multiple chapters. And even if one does not understand some phrases, there is google and stack overflow to be **searched** first. Last option is to ask here. – too honest for this site Aug 10 '16 at 14:37
  • @Olaf that is why I used _only_ in _italics_. For starting, it's good to read a book (or tutorial), get the basic idea of syntax and semantics, then, spec is always there for enhancement and / or correction of understanding. – Sourav Ghosh Aug 10 '16 at 14:40
  • @SouravGhosh: That's where I'm not sure. E.g. I did not learn C (or programming in general) from a book, but by self-teaching and soon used the standard, resp. snippets from it I found. (Hard to recap after all this time ...) – too honest for this site Aug 10 '16 at 14:51
  • `void main` is an invalid signature. Your compiler should complain! If not, enable warnings and pay heed to them! – too honest for this site Aug 10 '16 at 15:17
  • Thanks @Olaf: I'm not getting any warnings though. I'm using gcc via Cygwin. – trebor74 Aug 10 '16 at 15:26
  • @trebor74: Read my comment carefully **again**! – too honest for this site Aug 10 '16 at 15:28
  • @Olaf: Warnings are enabled and I'm dealing with legacy Unix C code, so am getting loads of warnings and gradually resolving, It's possibly because I'm using Cygwin which is a Unix emulator and probably has an older compiler? – trebor74 Aug 10 '16 at 15:32
  • `malloc` cannot return `0`. It can return a _null pointer, though. That is **not** the same! (And how do you know, you don't even test the result of `malloc`, which you **always** should?) – too honest for this site Aug 10 '16 at 15:56

1 Answers1

2

In your code, testArray itself is being passed-by-value. Any changes made to that inside the function, will not reflect back to the caller. You need to pass the address of the testArray, i.e., use a pointer to pointer.

In this condition,

  printf("main element 2 id = %d\n", testArray[1].id); 

in main() is basically accessing invalid memory which invokes undefined behavior.

You can, however, do something like

int getArray(TestType **testArray)
{

    *testArray = malloc(2 * sizeof(TestType));
    (*testArray[0]).id = 1;  
    //....
    //....

and

 int i = getArray(&testArray);

to get the desired behaviour.

That said, just to mention getArray(*&testArray); is the same as getArray(testArray);

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • You can't pass arrays by value to functions (and there is no pass-by reference in C). – too honest for this site Aug 10 '16 at 15:00
  • 1
    Many thanks for your help. I've just tried this exactly as you suggested and am still getting 0 as the output in `main()`. Do I need to change `testArray[1].id` to different syntax? – trebor74 Aug 10 '16 at 15:03
  • Actually the suggested code does return the first element of the array correctly, `testArray[0].id`. It's the second value only which is 0, `testArray[1].id`. – trebor74 Aug 11 '16 at 08:02