3

Yes, I've read this question & answers: Passing an array by reference in C?. I have a similar problem and implemented the same idea from that question.

However, I still get an error from the following code:

#include <iostream>

void FillArray(int** myArray)
{
   free( *myArray ) ;
   * myArray = (int*) malloc(sizeof(int) * 2);

   *myArray[0] = 1;
   *myArray[1] = 2;
}

int main()
{
   int* myArray = NULL;
   FillArray(& myArray);    
   return 0;
}

I got the following run-time error right after the FillArray function ends:

Unhandled exception at 0x773115de in Program.exe 0xC00000005: Access violation writing location 0xcccccccccc.

I'm using Visual Studio, opened Visual C++ Empty Project. And the file named main.cpp. Does that mean it's compiled with C++ compiler instead of C compiler? If so, how can I open a file which will be compiled only C compiler? I tried renaming main.cpp with main.c, but still have the same problem. (I'm asking this question, because I read some about "pass by reference" and saw that it's different in C and C++.)

Sorry for this very fundamental question.

I will be appreciated for any help,

Sait.

Community
  • 1
  • 1
Sait
  • 19,045
  • 18
  • 72
  • 99
  • 1
    There's no such thing as a reference in C... – Ed S. May 03 '12 at 20:12
  • Right, this is C++ not C. The reference to `iostream` is also a dead giveaway. – Justin Ethier May 03 '12 at 20:13
  • 2
    "Pass by reference" is just a generic way of referring to it. In C, passing by reference is implemented via pointers. Give the guy a break. – Matti Virkkunen May 03 '12 at 20:14
  • @MattiVirkkunen that's not even passing by reference though. That's passing a pointer by value. – Chris Eberle May 03 '12 at 20:14
  • @MattiVirkkunen: That's weird, I've been writing C a long time and I have never heard an experienced programmer use the term "pass by reference" in a C context because, you know, there is no such thing as passing by reference in C. Terminology matters. – Ed S. May 03 '12 at 20:16
  • What they said. Also, you forget to free your array at the very end, causing a memory leak. – Mr Lister May 03 '12 at 20:21
  • 1
    @EdS.: Passing by reference is language agnostic programming terminology. Or perhaps I should say "computer science". Whether C has C++-like references or not, if somebody asked me if C has pass by reference, I'd answer yes. – Matti Virkkunen May 03 '12 at 20:29
  • @MattiVirkkunen: No, no it is not, and saying things like that only serves to confuse beginners who don't understand that everything in C is pass by value (i.e., why you need an extra level of indirection if you need to initialize something to an entirely new memory location). You may answer yes, but you would be dead wrong. – Ed S. May 03 '12 at 20:30
  • @MattiVirkkunen: Passing by reference means the parameter will become an alias to the argument passed by the caller. This simply does not exist in C, so why use incorrect terminology? – Ed S. May 03 '12 at 20:33
  • @JustinEthier: Well yes, but calls to `malloc` and `free` don't make it clear, especially when you consider that the question was tagged as C – Ed S. May 03 '12 at 20:44
  • @EdS.: This is good stuff to know. I'd always assumed that passing a pointer was, by default, passing by reference since a pointer is (unless I was mistaken about it as well) a memory address. – devstruck May 03 '12 at 20:52
  • 2
    @post_erasmus: Exactly why we should use correct terminology :). In C, you are always passing a copy. If you pass a pointer, a copy of said pointer is made and passed to the function. Now, both pointers point to the same memory location, *but the pointers themselves are unique*. That is why this will work as intended `void foo(struct foo *p) { p->some_member = 1; }` but this will not `void foo(struct foo *p) { p = malloc(sizeof(struct foo)); }`. In the latter case only the copy will be modified. – Ed S. May 03 '12 at 20:57
  • 1
    calling by reference and calling by value are common idioms in programming. although they are not pure technical terms (eg. some consider java passes objects by reference others say references are passed by value instead), 'passing by reference' does not necessarily mean using 'reference' types in C++. – Tugrul Ates May 03 '12 at 21:17
  • @junjanes: Wikipedia disagrees with you, and so does most every programmer I know. http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference - These are two distinct terms that mean different things. Using them interchangeably serves only to confuse. – Ed S. May 03 '12 at 21:24

3 Answers3

10

Precedence is not working as you expect it to be. Try these:

(*myArray)[0] = 1;
(*myArray)[1] = 2;

(Note: iostream is not C. It's C++.)

Tugrul Ates
  • 9,451
  • 2
  • 33
  • 59
2

Your problem is one of operator precedence.

The [] operator binds more tightly than the * operator, so

*myArray[1] 

is the same as

*(myArray[1]).  

This is wrong, as the top level pointer only has enough memory allocated for one pointer. You want:

(*myArray)[1] = 2;

On a side note, there is no good reason to mix C and C++ like you have. Obviously you have C++ code here, so prefer new and delete over malloc and free because the latter two do not take into account constructors and destructors for complex objects.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • 3
    So the code does have problems, but there's a red herring here -- it's perfectly legal to call free on a NULL pointer. (It, as you may expect, does nothing.) – shanef22 May 03 '12 at 20:16
  • @shanef22: That's true, I should have clarified. – Ed S. May 03 '12 at 20:17
  • Yes. It could be, maybe, a bad practice; but as @shanef22 says, it didn't change anything. I still got the same error. – Sait May 03 '12 at 20:18
  • @zagy: I wrote my answer too quickly, sorry about that. It was actually a bit more subtle, see my updated response. – Ed S. May 03 '12 at 20:25
  • @EdS.: Sorry, I implemented junjanes answer first. :) Thanks for your answer and helping about the terminology as well ... – Sait May 03 '12 at 20:37
  • @zagy: No no, you chose the right one. He had the only correct answer before I edited mine (I even gave his a +1) – Ed S. May 03 '12 at 20:42
1

Good:

int main()
{
   int* myArray = NULL;
   FillArray(& myArray);   
   ...

Good:

void FillArray(int** myArray)
{
   * myArray = (int*) malloc(sizeof(int) * 2);

Catastrophically bad:

void FillArray(int** myArray)
{
   free( *myArray ) ;
   * myArray = (int*) malloc(sizeof(int) * 2);
   ...

Better:

void FillArray (int** myArray)
{
   if (myArray)
     free (*myArray);
   *myArray = (int*) malloc(sizeof(int) * 2);
   ...

ALSO:

   *(myArray[0]) = 1;
   *(myArray[1]) = 2;
paulsm4
  • 114,292
  • 17
  • 138
  • 190