tags:

views:

194

answers:

7

Dear all. I was wondering if there are examples of situations where you would purposefully pass an argument by value in C. Let me rephrase. When do you purposefully use C's pass-by-value for large objects? Or, when do you care that the object argument is fully copied in a local variable?

EDIT: Now that I think about it, if you can avoid pointers, then do. Nowadays, "deep" copying is possible for mostly everything in small apps, and shallow copying is more prone to pointer bugs. Maybe.

+1  A: 

Well, for one thing, if you want to change it.

Imagine the following contrived function:

int getNextCharAndCount (char *pCh);

Each time you call it, it returns the next most frequent character from a list by returning the count from the function and setting a character by way of the character pointer.

I'm having a hard time finding another use case which would require the pointer if you only ever wanted to use (but not change) the underlying character. That doesn't mean one doesn't exist of course :-)

In addition, I'm not sure what you're discussing is deep/shallow copy. That tends to apply to structures with pointers where a shallow copy just duplicates the top level while a deep copy makes copies of all levels.

What you're referring to is pass-by-value and pass-by-reference.

paxdiablo
In that case, you are passing a pointer a char, not a copy of the char, unless you mean you're passing a copy of the address of some char variable, but that's a shallow copy, not a deep one.
Pete Kirkham
+1  A: 

Passing by-reference is cheaper because you don't have to create a local copy of an object. If the function needs a local copy (for any purpose) - that could be a case.

adf88
Not necessarily. Pass by reference means you need a pointer created and a dereference to get at it. If the element being passed fits in an architecture's register, then it is actually cheaper to pass by value.
Michael Dorgan
This was obvious. Topic is about large objects.
adf88
A: 

I don't think your argument about chars holds water. Even though your char is conceptually 1 byte, each argument to a function call typically translates to a whole (word-sized) register and to the same amount of space on the stack for efficiency.

You can pass a whole struct on the stack as an argument if you really want to (and, I believe, return them as well). It's a way of avoiding both allocating memory and having to worry about pointer hygiene.

crazyscot
There's also the question of whether it matters if there's a bit of extra space used. The answer to that one is usually (although certainly not always) "no".
David Thornley
A: 

Depending on how the call stack is built the char and char* may take the same amount of space. It is generally better to have values aligned on word boundaries. The cost of accessing a 32 bit pointer on a word boundary may be significantly lower than accessing it on a non-word boundary.

Passing by value is safer if you don't want the value modified. Passing by reference can be dangerous. Consider passing by referennce

CONST int ONE = 1;
increment( *ONE );
print ONE;

Output is 2 if the constant was modified.

BillThor
psmears
Increment could copy it parameters and convert it into a pointer, to a non-constant, then dereference the pointer. There are suicidal techniques to do this.The failure occurs in some languages (FORTRAN), and is the simple case. Consider 1 were replaced an object pointer or an object holding a referece. The problem is much more generalized. The more indirect the reference, the more likely you get to modify something that should be static. Deep copies are memory and CPU intensive, but protect your objects.
BillThor
+1  A: 

I follow as a rule:

  • pass built-in types by value (int, char, double, float...)
  • pass classes and structs by (const) reference. There is no pointer handling involved whatsoever.

Never had any problems with this way of work.

rubenvb
+2  A: 

In C (sans const references), you pass by value for 3 reasons.

  • You don't want the source to be modified by the receiving function outside of its context. This is (was) the standard reason taught in school as it why to pass by value.

  • Passing by value is cheaper if the value fits within the architecture's register - or possibly registers if the compiler is very intelligent. Passing by value means no pointer creation and no dereference to get at the value being passed in. A small gain, but it does add up in certain circumstances.

  • Passing by value takes less typing. A weak reason to be sure, but there it is.

The const keyword negates most of reason 1, but reason 2 still has merit and is the main reason I pass by value.

Michael Dorgan
Someone should say that C only support call-by-value anyway.
Skeptic
Not true. You can pass a pointer to the object which is what pass by reference is doing under the hood for you.
Michael Dorgan
+1  A: 

If we're going to be pedantic about this, everyhing in C is pass-by-value. You may pass a pointer by value instead of passing the actual object by value, but it's still pass-by-value.

Anyway, why pass an entire object instead of a pointer to an object? Well, for one, your compiler may be able to optmize the call such that underneath the covers only an address is copied. Also/Alternatively, once you introduce pointers, your compiler may not be able to do as much optimization of your function because of aliasing. It's also less error prone to not have to remember to dereference. The caller can also be sure that what he passed in is not modified (const doesn't really guarantee this, it can be -dangerously- cast away)

frankc