Pass by reference in C

49,667

Solution 1

C does not have references. You need to pass a pointer to the variable you wish to modify:

int locate(char *name, int *s, int *i)
{
    /* ... */

    *s = 123;
    *i = 456;
}

int s = 0;
int i = 0;
locate("GMan", &s, &i);

/* s & i have been modified */

Solution 2

C has no reference variables but you can consider reference as const pointer to data so ,

Make const pointer to data like this so that pointer cant point to other data but data being pointed by it can be changed.

int  locate (char *name,  int  * const s, int * const i)

Solution 3

C does not support pass by reference. You'll need C++ to do it the way it is written, or modify into

int locate(char *name, int *s, int *i)

and pass pointers to the second and third parameter variables.

Solution 4

You can't do this in c. c doesn't have reference, you can use pointer instead.

Solution 5

The earlier answers given seem to be missing context, and don't address the property that C pointers are overloaded. It's completely fair to claim that C "passes by reference." A pointer is a reference, too. However, more formally, a C "reference" is the mechanism to represent a symbol's memory address.

  • A pointer is simply a variable in memory whose value is treated as an address.
  • A reference is simply the value-literal for a memory address.
  • The C language allows for passing by reference - but only in the right context!

The separation of context is that of signature definition and signature invocation.

Consider the primitives int a = 0x22e8; and somewhere else we declare int* b = &a; (I'll get to functions in a minute).

We could visualize this in memory (assume endianness doesn't matter for this example):

...
0x00000200:        22e8        ; this is the variable for int a's literal value:
                               ; a == 0x000022e8
                               ; &a == 0x00000200
0x00000???:        9090        ; ... more code ...
0x00000400:        0200        ; this is pointer b pointing to a's address:
                               ; b == 0x00000200
                               ; *b == 0x000022e8
                               ; &b == 0x00000400
...

It's easy to see that we can assign a pointer to any address without any special tricks. A pointer is just a variable, but C allows us to reference the address it's pointing to; we can "dereference" the pointer from its value-address to instead treat the pointer as its pointee's underlying value during an invocation context: while ( *b == a ) .... We could easily invoke b == &a.

When applying this to function calls, you have to separate the context of function (signature) definition vs invocation in order to differentiate pass by reference.

int* foo(int* blah, int nah) { .. }     // signature definition context:
                                        // These are parameters
... vs ...

b = foo( &a, 4);                        // invocation context:
                                        // These are arguments

In defining a function signature, we are not telling the compiler which address an argument is accessed from — the runtime doesn't even know yet! It's just nonsense to define void bar(int &blah) {...}. Instead we use the dereferenced pointer syntax — "whatever argument is passed in will be loaded at the address pointed to" — to reference the desired argument value when runtime occurs. Thus C can pass arguments by reference.

The contexts of both function signature definitions and function calls change how the compiler looks at pointer overloading vs reference, and how the runtime can actually address them.

Share:
49,667
neuromancer
Author by

neuromancer

Updated on July 09, 2022

Comments

  • neuromancer
    neuromancer almost 2 years

    I'm trying to use pass by reference in C so that the function can modify the values of the parameters passed to it. This is the function signature:

    int locate(char *name, int &s, int &i)
    

    However when I try to compile it I get this error that refers specifically to the above line:

    error: expected ‘;’, ‘,’ or ‘)’ before '&' token

    If I remove the '&' the program will compile, but it will not function correctly, obviously. What's wrong here? How can I make call by reference work?

  • cadaniluk
    cadaniluk over 8 years
    I'm pretty sure name is not supposed to be a pointer to a single char.
  • ToFue
    ToFue almost 7 years
    To be clearer, an actual C "reference" syntax is the ampersand syntax: &a.And also "pass by reference," the b = foo(&a,4), occurs at runtime during function call execution; and signature definition, the int* foo(int* a, int nah){..} is the setup to allow the reference passing.
  • vincent thorpe
    vincent thorpe over 4 years
    what do you mean with "doesnt have references". you clearly are using & reference operator locate("GMan", &s, &i);. be more explicit.
  • 6equj5
    6equj5 over 3 years
    Though C++ and Rust use & for references, C doesn't actually have references -- it only has pointers. In C++, & means "give me a reference to this". C, & means "give me a pointer to this (i.e., give me this thing's address in memory)". As a result, you can't declare a reference: int &x = &i; is valid C++ but is invalid C (it must be int *x = &i;). You also can't have a reference parameter in a function: foo(int &x) is valid C++ but is invalid C (it must be foo(int *x)).
  • Sam Ginrich
    Sam Ginrich about 2 years
    E.g. ´*s´ is a reference
  • Sam Ginrich
    Sam Ginrich about 2 years
    More precisely "When p is a pointer then *p is a reference". This follows, when we embed the C grammar into C++ terminology.
  • Sam Ginrich
    Sam Ginrich about 2 years
    "you would use pointers pointing to the addresses" it is "pointers are addresses". Latter version of function locate exists in C++, only.