Passing pointer by reference in C
In C, pass by reference is emulated by passing a pointer to the desired type. That means if you have an int *
that you want to pass to a function that can be modified (i.e. a change to the int *
is visible in the caller), then the function should accept an int **
.
In your specific case however, this isn't what you want. You only need to pass an int *
to your function which it can then dereference implicitly via the []
operator and change the elements of the array.
void sort(int *arr, int s, int e)
{
int temp = 0, i, j;
for (i=0;i<e;i++)
{
for (j=i+1;j<e;j++)
{
if (arr[i]>arr[j])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
why can't we pass the pointer by reference in C?
From The C Programming Language - Second Edition (K&R 2):
5.2 Pointers and Function Arguments
Since C passes arguments to functions by value, there is no direct way
for the called function to alter a variable in the calling function....
Pointer arguments enable a function to access and change objects in
the function that called it.
If you understand that:
void fn1(int x) {
x = 5; /* a in main is not affected */
}
void fn2(int *x) {
*x = 5; /* a in main is affected */
}
int main(void) {
int a;
fn1(a);
fn2(&a);
return 0;
}
for the same reason:
void fn1(element *x) {
x = malloc(sizeof(element)); /* a in main is not affected */
}
void fn2(element **x) {
*x = malloc(sizeof(element)); /* a in main is affected */
}
int main(void) {
element *a;
fn1(a);
fn2(&a);
return 0;
}
As you can see, there is no difference between an int
and a pointer to element, in the first example you need to pass a pointer to int
, in the second one you need to pass a pointer to pointer to element.
Passing by reference in C
Because you're passing the value of the pointer to the method and then dereferencing it to get the integer that is pointed to.
Can I take a reference of a pointer in C++?
I am not sure what your problem is, as the error code given does not match your code.
Your second example with int Foo(const Obj* &ptr)
works exactly as intended, and compiles fine if you make DoSomething
const.
To comment your three thoughts:
- If you const things correctly, the error goes away.
- I really, really dislike such out-paramteres. It is much cleaner to return a struct or a pair of int and pointer. That way the caller can write
const auto[ret, p] = Foo();
and not have to explicitely declare the pointer that you may not want to use. - Passing pointers to pointers is C-style, due to lack of references, and just make the code harder to read, with no benefit.
Below is slightly modified code that compiles fine, with a better Foo too, as mentioned in my answer to 2.:
#include <utility>
struct Obj
{
void DoSomething() const;
};
// This is ugly of course, used just to have a valid ptr to return
Obj global;
int Foo(const Obj* &ptr) {
// do something...
ptr = &global;
return 5;
}
std::pair<int, const Obj*> BetterFoo()
{
// do something...
return {5, &global};
}
int main() {
const Obj* p1 = nullptr;
int ret1 = Foo(p1);
const auto[ret2, p2] = BetterFoo();
p1->DoSomething();
p2->DoSomething();
}
Is passing pointer by value or by reference the same
What is the difference between passing a pointer by reference and passing a pointer by value in C?
There is no such thing as passing a pointer by reference in C, all variables are passed by value, even pointers.
My understanding is when you pass arguments to methods a new stack frame is created and those values are copied to different memory addresses unless passed by reference. If passed by reference the memory addresses are passed.
Again, the pointers are not passed by reference, a copy of the value stored in the pointer is passed, i.e. the address where it points to, you can test this by changing the value of the pointer inside the function, and check how that reflects on the original pointer, spoiler, it doesn't.
When working with pointers I noticed that if I pass a char by value and modify it in a different stack frame when I return back to the main stack frame the value of the ptr has been modified.*
What you are passing is an address, a memory location where some data is stored, when you change the data stored in that memory address it will be permanent, no matter where you do it, in fact that is one of the advantages of using pointers, for you to change the contents of some variable outside the scope where it's declared.
Pass by reference and pointers
There is no pass by reference in C, it's always pass by value.
C developers can emulate pass by reference, by passing the pointers to a variable and the accessing it using dereferencing within the function. Something like the following, which sets a variable to 42
:
static void changeTo42 (int *pXyzzy) {
*pXyzzy = 42;
}
:
int x = 0;
changeTo42 (&x);
Contrast that with the C++ true pass by reference, where you don't have to muck about with pointers (and especially pointers to pointers, where even seasoned coders may still occasionally curse and gnash their teeth):
static void changeTo42 (int &xyzzy) {
xyzzy = 42;
}
:
int x = 0;
changeTo42 (x);
I would implore ISO to consider adding true references to the next C standard. Not necessarily the full capability found in C++, just something that would fix all the problems people have when calling functions.
C - pass by reference?
pass them as pointers. If you do not return the value - declare functions void, or return something
void doStuff(int *v)
{
*v = *v + 10; // main->value = 10
}
void otherStuff(int *v)
{
*v = *v - 10; // main->value = 0
}
and in the main
doStuff(&value); // "value" = 10
/*....*/
otherStuff(&value); // "value" = 0
int *v in the function means that v is the pointer to the int object.
in the function call &value passes the pointer (address) to the value.
Dereferencing the pointer v in the function - all poerations are actuqally done on the value.
Related Topics
Scope of Variables in If Statements
G++ "Calling" a Function Without Parenthesis (Not F() But F; ). Why Does It Always Return 1
How to Know Which Parts in the Code Are Never Used
Initialize Parent's Protected Members with Initialization List (C++)
How to Convert a Reverse Iterator to a Forward Iterator
Round a Float to a Regular Grid of Predefined Points
Matching Alias Template as Template Argument
Os Specific Instructions in Cmake: How To
C++ Exception:Throwing Std::String
About Binding a Const Reference to a Sub-Object of a Temporary
Unit Testing for C++ Code - Tools and Methodology
How to Declare a Global Variable in C++
How to Check If an Object's Type Is a Particular Subclass in C++
C++ Header Files, Code Separation
Template Partial Ordering - Why Does Partial Deduction Succeed Here