Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do C++ compilers actually pass reference parameters?

This question came about as a result of some mixed-language programming. I had a Fortran routine I wanted to call from C++ code. Fortran passes all its parameters by reference (unless you tell it otherwise).

So I thought I'd be clever (bad start right there) in my C++ code and define the Fortran routine something like this:

extern "C" void FORTRAN_ROUTINE (unsigned & flag);

This code worked for a while but (of course right when I needed to leave) suddenly started blowing up on a return call. Clear indication of a munged call stack.

Another engineer came behind me and fixed the problem, declaring that the routine had to be defined in C++ as

extern "C" void FORTRAN_ROUTINE (unsigned * flag);

I'd accept that except for two things. One is that it seems rather counter-intuitive for the compiler to not pass reference parameters by reference, and I can find no documentation anywhere that says that. The other is that he changed a whole raft of other code in there at the same time, so it theoretically could have been another change that fixed whatever the issue was.

So the question is, how does C++ actually pass reference parameters? Is it perhaps free to do copy-in, copy-out for small values or something? In other words, are reference parameters utterly useless in mixed-language programming? I'd like to know so I don't make this same code-killing mistake ever again.

like image 451
T.E.D. Avatar asked May 29 '10 22:05

T.E.D.


People also ask

How does pass-by-reference work in C?

Passing by by reference refers to a method of passing the address of an argument in the calling function to a corresponding parameter in the called function. In C, the corresponding parameter in the called function must be declared as a pointer type.

How are parameters passed by reference?

Pass-by-reference means to pass the reference of an argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the argument by using its reference passed in. The following example shows how arguments are passed by reference.

How does C pass parameters?

A Parameter is the symbolic name for "data" that goes into a function. There are two ways to pass parameters in C: Pass by Value, Pass by Reference.

Does C language support pass-by-reference?

There is no pass-by-reference in C.


1 Answers

C++ doesn't define how implementations should be, it's just a language. So there isn't "a" implementation of references.

That said, references are implemented with pointers. This leads to a lot of confusion ("references are just pointers", "references are just pointers with the mundane parts taken out") but that is not the case. References are aliases and will always be aliases.

The compiler will pass the address of a variable, and operate with that pointer. This has the same effect (but not the same semantics!). To be more concrete, a compiler might "replace" this:

void make_five(int& i)
{
    i = 5;
}

int main(void)
{
    int i = 0;
    make_five(i);
}

With this:

void make_five(int* const i)
{
    *i = 5;
}

int main(void)
{
    int i = 0;
    make_five(&i);
}

(In practice such a simple function would be inlined, but you get the point.) Hence why your colleague suggested you use a pointer.

Keep in mind references are to be preferred. This is where the distinction between references and pointers is important. Do you want to alias a variable, or do you want to point at it? Most of the times, the former. In C, you had to use a pointer to do this, and this contributes to the common C-programmer misconception that references are actually pointers.

To get similar semantics (since you are now pointing to a variable, and not aliasing it), you should ensure the value of the pointer is not null:

extern "C" void FORTRAN_ROUTINE (unsigned * flag)
{
    assert(flag); // this is normally not a problem with references, 
                  // since the address of a variable cannot be null.

    // continue...
}

Just to be safe.

like image 179
GManNickG Avatar answered Oct 19 '22 07:10

GManNickG