3

I am dusting off my C skills working on some C libraries of mine. After having put together a first working implementation I am now going over the code to make it more efficient. Currently I am on the topic of passing function parameters by reference or value.

My question is, why would I ever pass any function parameter by value in C? The code might look cleaner, but wouldn't it always be less efficient than passing by reference?

c00kiemonster
  • 22,241
  • 34
  • 95
  • 133
  • 11
    **Every** argument is passed by value in C. And if it's not larger than a pointer, passing a copy certainly isn't less efficient. – Daniel Fischer Jan 04 '13 at 01:45
  • Not to mention how inconvenient that would be: `int get_int(); void process_int_A(const int x); void process_int_B(const int* const x);`. Compare: `void foo(){ process_int_A(get_int()); }` vs. `void foo(){ const int result = get_int(); process_int_A(&result); }`. Needing explicit intermediate storage for every return value would be killer. It's less of an issue in C++, where you have "real" references that can bind to temporary values just fine. – GManNickG Jan 04 '13 at 01:48

4 Answers4

6

Because it's not as important to code for the computer as it is to code for the next human being. If you are passing references around then any reader must assume that any called function could change the value of his parameters and would be obligated to check it or copy the parameter before calling.

Your function signature is a contract and divides your code up so that you don't have to fit the entire code base into your head in order to comprehend what is going on in some area, by passing references you are making the next guy's life worse, your biggest job as a programmer should be making the next guy's life better--because the next guy will probably be you.

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • 1
    Good answer. Also, passing by value can actually be faster because (among other things) the compiler knows the arguments do not alias each other and may therefore generate better code. – Nemo Jan 04 '13 at 01:57
  • The "making the next guy's life worse" example is a good one, that is something I had overlooked. – c00kiemonster Jan 04 '13 at 02:05
  • And I always thought the next guy is a homicidal maniac who knows your address. – Daniel Fischer Jan 04 '13 at 02:07
4

In C, all arguments are passed by value. A true pass by reference is when you see the effect of a modification without any explicit indirection at all:

void f(int c, int *p) {
  c++; // in C you can't change the original paramenter passed like this
  p++; // or this
}

Using values instead of pointers though, is frequently desirable:

int sum(int a, int b) {
    return a + b;
}

You would not write this like:

int sum(int *a, int *b) {
    return *a + *b;
}

Because it is not safe and it is inefficient. Inefficient because there is an additional indirection. Moreover, in C, a pointer argument suggests the caller that the value will be modified through the pointer (especially true when the pointed type has a size less than or equal to the pointer itself).

perreal
  • 94,503
  • 21
  • 155
  • 181
  • This might be a silly question, but why is the ```int sum(int *a, int *b) { return *a + *b; } ``` function unsafe? – c00kiemonster Jan 04 '13 at 02:02
  • because then you have the risk of indirecting NULL/dangling pointers which never happens without pointers. – perreal Jan 04 '13 at 02:05
  • 4
    The caller now is required to create a variable for a and b, no constants can be passed. The caller also has to decide if they need to `malloc` the values or pass the address of variables and assume that the value might be modified since they are not `const` (possibly needing to copy the values). Also dereferencing pointers is not be safe if the caller passes `NULL`, uninitialized pointers and/or pointers to an invalid memory location. – Joe Jan 04 '13 at 02:06
1

Please refer to Passing by reference in C. Pass by reference is a misnomer in C. It refers to passing the address of a variable instead of the variable, but you are passing a pointer to the variable by value.

That said, if you were to pass the variable as a pointer, then yes it would be marginally more efficient, but the main reason is to be able to modify the original variable it points to. If you don't want to be able to do this, it is recommended you take it by value to make your intent clear.

Of course, all this is moot in terms of one of Cs heavier data structures. Arrays are passed by a pointer to their first variable whether you like it or not.

Community
  • 1
  • 1
Karthik T
  • 31,456
  • 5
  • 68
  • 87
0

Two reasons:

  1. Often times you will have to dereference the pointer you've passed in many times (think a long for-loop). You don't want to dereference every single time you want to look up the value at that address. Direct access is faster.

  2. Sometimes you want to modify the passed-in value inside you function, but not in the caller. Example:

    void foo( int count ){
        while (count>0){
            printf("%d\n",count);
            count--;
        }
    }
    

If you wanted to do the above with something passed by reference, you would haev to create yet another variable inside your function to store it first.

Phonon
  • 12,549
  • 13
  • 64
  • 114
  • What is the performance penalty to dereference a variable versus direct access? Is it in order-of-magnitude land? – c00kiemonster Jan 04 '13 at 01:55
  • It can be 3 cycles versus 1 cycle. If you're programming for a quad-core machine, who cares (mainly)? If you're building anything performance based (real-time applications, embedded systems), this could make a huge difference. – Phonon Jan 04 '13 at 01:57
  • Profile, profile, profile! Part 1 of this answer is extremely speculative and does not take compiler optimizations into account. – Dan Bechard Jan 18 '17 at 19:49