views:

183

answers:

4

Hi,

I have encountered a working (with XLC8 and MSFT9 compilers) piece of code, containing a c++ file with a function defined with c linkage and a reference argument. This bugs me, as references are c++ only. The function in question is called from c code, where it is declared as taking a pointer argument to the same type in place of the reference argument.

Simplified example:

c++ file:

extern "C" void f(int &i)
{
  i++;
}

c file:

void f(int *);

int main()
{
  int a = 2;
  f(&a);
  printf("%d\n", a);  /* Prints 3 */
}

Now, the word on the street is that most c++ compilers, under the hood, implement references just like a pointer. Is that and just pure luck the reason this code works or does it say somewhere in the c++ specification what the result is when you define a function with a reference argument and c linkage? I haven't been able to find any info on this.

+10  A: 

In many cases, but not all, a reference can be implemented with an 'auto-dereferenced' pointer. That any particular compiler treats a function with C linkage and a reference parameter this way is not guaranteed in the C++ standard, and you should treat it as an implementation detail.

It isn't hard to write a forwarding function that takes a pointer and calls your function, if you need to do this without relying on implementation details:

void real_f(int& n) {
  n++;
}
extern "C" void f(int* p) { // called from C code
  real_f(*p);
}
Roger Pate
+3  A: 

A reference is an alternate name for an object. Technically, there is nothing in C that could map directly to a C++ reference.

The obvious implementation of a reference is as a (constant) pointer that is dereferenced each time it is used. So, depending on how your compiler implements references, your code might work. But it is not correct.

The solution is to write a C function that receives either a real object or a pointer to that object and call the C++ function from this.

Vijay Mathew
It is not guaranteed, but it is not necessarily incorrect. How other languages call C++ functions (including `extern "C"` C++ functions) is outside the scope of the C++ standard. And as far as C is concerned, the function has been correctly declared and called. This is an implementation issue, and whether you may, should, or must not depend on it will vary by project requirements.
Roger Pate
+4  A: 

That's what Bjarne Stroustrup has to say about references:

"Most references are implements are implemented using a pointer variable; that it a reference usually takes up one word of memory. However, a reference that is used purely locally can - and often is - eliminated by the optimizer".

For example:

 struct S 
 { 
    int a;
    int b[100]; 
 };  // just an example

 void do_something(const vector<S>& v)
 {
    for (int i=0; i<v.size(); ++i)
    {
        int(&p)[100] = v[i].b;
        for (int j=0; j<100; ++j) 
           cout <<p[j];
    }
 }

In this case, p needs not be stored in memory (maybe it just exists in a register, maybe it disappears into the instructions).

Prasoon Saurav
You mean `int (`; also s/,/;/ and v.size().
Roger Pate
@Roger : Thanks, I've edited my post :)
Prasoon Saurav
It would be nice if you gave a more complete citation. *Where* did Stroustrup say that? (Web site, or book title, edition, and page number) On the other hand, we *already know* references are often implemented as pointers. That's why the code in the question works as it does today. I don't see the point you were trying to make with this answer, especially in regard to parameters of functions with C linkage.
Rob Kennedy
+2  A: 
Alok
Entirely correct quote, but note that it also has an upside: since it's implementation-defined anyways, if it works it works.
MSalters
Yes, but maybe it works because it works with that particular version of the compiler? I tried looking at gcc documentation but couldn't find any information. As far as I understand it, the question is more of a "theoretical" question, trying to find out if the standard allows such declarations. I doubt if the OP wants to do such a thing in real code, given that it's so easy to avoid doing it.
Alok
Well the code is in production and works, but I'd like to keep the code standards compliant as new platforms or compilers may be targeted in the future.
olovb
In this case, I think the standard is pretty clear so if changing the code is easy, you should do it.
Alok
@Alok, Yes. It is for the best.
olovb