Function parameter or local variable - c

Let's say I have a loop which repeats millions of times. Inside of this loop I have a function call.
Inside of this function I need to operate on some temporary variable created at the very beginning. Now, which one is better:
a) Create temporary variable at the beginning of the code, initialize it at the beginning of the loop, and pass it as function parameter
b) Create just local temporary variable at the beginning of the called function?
Is this answerable question? I'd like to know which point is considered better practice, or which one is faster.

Let's throw up some possible definitions for some_function(), the function you will be calling from your loop.
// Method 1
void some_function() {
int temporary;
// Use temporary
}
// Method 2
void some_function(int temporary) {
// Use temporary
}
// Method 3
void some_function(int *temporary) {
// Use *temporary
}
Method 1 is likely to be the most readable out of these options, and so it's the one I would prefer unless you have a really good reason to do something else. It is also likely to be faster than either of the others, unless your compiler is inlining the function call. If it is, then all three are likely to perform exactly the same (method 3 might still be slower if the compiler isn't able to optimize away the pointer dereferences).
If the compiler is not inlining, then method 2 is likely to be slower than method 1. This is because, in terms of stack-allocated memory, they are the same -- function arguments are going to be stored on the stack the same way locals are. The only difference between a function argument and a local in this context is that the function argument can be given a value by the caller. This step of transferring the value from the caller to the function is (theoretically) going to slow down the invocation.
Method 3 is almost certainly going to be slower, since accesses to the temporary memory will include a level of indirection. Dereferencing a pointer is not a cheap operation compared to accessing a local.
Of course, if performance is absolutely critical then you should benchmark these approaches. I suspect that method 1 will turn out to be the fastest (or at least no slower than the others) and additionally seems more readable to me.

If the variable is not needed outside the function, then it should be inside the function. This allows the compiler to do the best job of optimising the code, as well as making the code most readable and easy to use (this applies generally, "declare variables with the smallest possible scope", although for small functions, declaring a handful of variables at the top of the function each time is the best option).
From a performance perspective, passing a variable to a function is either equivalent, or worse than having a local variable. [And of course, the compiler may inline everything and you end up with exactly the same code in both cases, but that's dependent on the compiler and the code you have].
As others have mentioned, passing a pointer to a local variable will incur a "penalty" for accessing the pointer to get the value. It may not make a huge difference, but it almost certainly makes some difference. This should definitely be the last resort. [Note that if the variable is LARGE, the overhead of passing a copy to the function may still be worse than the overhead of a pointer. But if we assume it's a simple type like int or float, then a pointer has noticeable overhead].
Any time there is a question on performance, you DEFINITELY should benchmark YOUR code. Asking someone else on the internet may be worthwhile if there is a choice between algorithms for sorting or something like that, but if it's a case of "is it better to do this or that" in some more subtle differences, then the differences are often small and what your particular compiler does will have much more influence than "which is theoretically better".

There is a subtle difference between these two approaches if you are passing the variable as a pointer, rather than a value. The pointer will get pushed onto the call stack and will have to be referenced in order to get/set the value.
Conversely, setting it as a local value, or pass by value, will put the value on the stack. It matters not whether it is a local or pass by value in that case... though there is one possible caveat based on how the variable is handled outside of the function in the case of pass by value... if it is stored in a variable (not passing a literal value) then it has to get fetched from memory and pushed on the stack. If it is set from a literal value inside the function, it is just a literal pushed on the stack and saved a memory cycle.
A third option you omit is the use of a global variable.
On the off chance the value is constant, always, then the best answer use a #define and compile it directly into the code as a literal.

Related

C: When to return by value or pass reference

Although the subject is discussed many times, I haven't found any satisfying answer so far. When to return data from a function by return or to pass a reference to change the data on address? The classic answer is to pass a variable as reference to a function when it becomes large (to avoid stack copying). This looks true for anything like a structure or array. However returning a pointer from a function is not uncommon. In fact some functions from the C library to the exact thing. For example:
char *strcat(char *dst, const char *src);
Always returns a pointer to destination even in case of an error. In this case we can just use the passed variable and leave the return for what it is (as most do).
When looking at structures I see the same thing happening. I often return pointers when functions only need to be used in variable initialization.
char *p = func(int i, const char *s);
Then there is the argument that stack coping variables is expensive, and so to use pointers instead. But as mentioned here some compilers are able to decide this themselves (assuming this goes for C as well). Is there a general rule, or at least some unwritten convention when to use one or the other? I value performance above design.
Start by deciding which approach makes the most sense at the logical level, irrespective of what you think the performance implications might be. If returning a struct by value most clearly conveys the intent of the code, then do that.
This isn't the 1980s anymore. Compilers have gotten a lot smarter since then and do a really good job of optimizing code, especially code that's written in a clear, straightforward manner. Similarly, parameter passing and value return conventions have become fairly sophisticated as well. The simplistic stack-based model doesn't really reflect the reality of modern hardware.
If the resulting application doesn't meet your performance criteria, then run it through a profiler to find the bottlenecks. If it turns out that returning that struct by value is causing a problem, then you can experiment with passing by reference to the function.
Unless you're working in a highly constrained, embedded environment, you really don't have to count every byte and CPU cycle. You don't want to be needlessly wasteful, but by that same token you don't want to obsess over how things work at the low level unless a) you have really strict performance requirements and b) you are intimately familiar with the details of your particular platform (meaning that you not only know your platform's function calling conventions inside and out, you know how your compiler uses those conventions as well). Otherwise, you're just guessing. Let the compiler do the hard work for you. That's what it's there for.
Rules of thumb:
If sizeof(return type) is bigger than sizeof(int), you should probably pass it by pointer to avoid the copy overhead. This is a performance issue. There's some penalty for dereferencing the pointer, so there are some exceptions to this rule.
If the return type is complex (containing pointer members), pass it by pointer. Copying the local return value to the stack will not copy dynamic memory, for example.
If you want the function to allocate the memory, it should return a pointer to the newly allocated memory. It's called the factory design pattern.
If you have more than one thing you want to return from a function - return one by value, and pass the rest by pointers.
If you have a complex/big data type which is both input and output, pass it by pointer.

In term of optimization, What is the difference between defining function pointer with argument and without argument

I know that defining function pointer in this way
struct handler_index {
const char *name;
int (*handler)();
};
allow to use handler pointer for any function with unspecified (but non-variable) number and types of parameters.
but I m wondering if this definition could affect the optimization of code or memory or execution time comparing to this:
struct handler_index {
const char *name;
int (*handler)(int a, int b);
};
If you're wondering how adding more parameters to a function pointer affects specifically the function pointer -- it doesn't. Function pointers are all the same size regardless of the number of parameters.
If you're wondering about efficiency of calling such a function pointer: adding more parameters will result in code being generated to pass arguments. So yea, it will affect code size of the call slightly, and maybe execution time depending on how much ILP your CPU can pull off while passing those args.
Modern calling conventions often pass some number of arguments in registers, so you may or may not have an increase in stack usage.
To see exactly what the difference is between code generated for each call, read up on calling conventions (there are too many to list here!) and check the asm generated from your code. But really, adding more parameters (within reason) is probably going to have such a vanishingly small effect that it simply doesn't matter.
As Cory says, it's not really relevant whether it is a function pointer or just a regular basic function [except in cases where a regular function gets inlined, which of course, function pointers generally can't - although if the situation is specific enough I have seen the compiler actually figure out "Ah, we're always calling function X here, so lets inline X" - typically when the function pointer is an argument to a function, rather than say in a structure).
What WILL make a difference is adding arguments to function calls in general. The processor will have to place those arguments somewhere, and even if they go in registers, it may require extra instructions to get the value into the RIGHT register.
However, your first example is very bad because there's no check that your code is doing the right thing.
Further, you need some pretty pathological cases to make the overhead of passing arguments to a function to be much of the time of calling a function pointer - hopefully your function does more than add one number to another.
Having said that, passing LOTS of arguments, especially "hard to get" arguments can be really bad. I was working on a graphics chip simulator, and part of the pixelshader processing unit had a debug print in the middle of it, which rarely got printed, but it took something like 7 or 8 arguments (aside from the debug level of 1000 or whatever it was). Fishing out those arguments from the respective structures and sticking them on the stack took quite some time, and putting an "if (debuglevel >= 1000) ..." so that the call was only made when it was actually needed, made the code some 40% faster in that function.

When to pass by value?

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.
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.
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.
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.
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.
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)
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.
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.

Modifying arguments 'passed by value' inside a function and using them as local variables

I have seen some code in which the arguments passed to the function by value was being modified or assigned a new value and was being used like a local variable.
Is it a good thing to do? Are there any pitfalls of doing this or is it Ok to code like this?
Essentially, a parameter of a function is a local variable, so this practice is not bad in principle.
On the other hand, doing this can lead to maintenance headaches. If another programmer comes along later, he might expect the variable to hold the passed in value, and the change will cause a bug.
One justification for reusing the variable is for a misguided notion of efficiency of memory usage. Actually, it can't improve efficiency, and can decrease it. The reason is that the compiler can automatically detect if it is useful to use the same register for two different variables at two different times, and will do it if it is better. But the programmer should not make that decision for the compiler. That will limit the choices the compiler can make.
The safest practice is to use a new variable if it needs a new value, and rely on the compiler to make it efficient.
No problems at all that I can think of. The arguments will either be placed in the current stack frame or in registers just like any other local variable. Make sure that the arguments are passed by value, however. In particular, arrays are passed by reference.

Efficiency of C Variable Declaration [duplicate]

This question already has answers here:
How is conditional initialization handled and is it a good practice?
(5 answers)
Closed 9 years ago.
How long does it take to declare a variable in C, for example int x or unsigned long long var? I am wondering if it would make my code any faster in something like this.
for (conditions) {
int var = 0;
// code
}
Would it be faster to do this, or is it easier not to?
int var;
for (conditions) {
var = 0;
// code
}
Thanks for the help.
One piece of advice: stop worrying about which language constructs are microscopically faster or slower than which others, and instead focus on which ones let you express yourself best.
Also, to find out where your code is spending time, use a profiler.
And as others have pointed out, declarations are purely compile-time things, they don't affect execution time.
It doesn't make any difference. In a traditional implementation the declaration itself (excluding initialization) generates no machine instructions. Function prologue code typically allocates space in the stack for all local variables at once, regardless of where they are declared.
However, where you declare your local variables can affect the performance of your code indirectly, in theory at least. When you declare the variables as locally as possible (your first variant), in general case it results in smaller size of the stack frame reserved by the function for its local variables (since the same location in the stack can be shared by different local variables at different times). Having smaller stack frame reduces the general stack memory consumption, i.e. as nested function calls are performed stack size doesn't grow as fast (especially noticeable with recursive functions). It generally improves performance since new stack page allocations happen less often, and stack memory locality becomes better.
The latter considerations are platform-dependent, of course. It might have very little or no effect on your platform and/or for your applications.
Whenever you have a question about performance, the best thing to do is wrap a loop around it (millions of iterations) and time it. But, in this case, you will likely find that it makes no difference.
It is more important to properly express the intentions of your code. If you need the variable outside your loop, delare it outside. If you only need the variable inside the loop, declare it inside.
You should always declare and initialize variables in narrowest scope possible.
You shouldn't be worrying about those types of micro-optimizations anyway (except in the rarest, rarest of cases). If you really need to worry about potential nano-second performance improvements, measure the difference. It is very unlikely that your variable declarations will be the largest bottleneck in your application.
It takes no time at all. The memory for global variables is allocated at startup, and "declaring" variables on the stack simply involves how far "up" the stack pointer moves when the function is called.
declarations are purely compile time, they cost nothing at runtime¹. But the first piece of code is still better than the second for two reasons
you should always initialize variables when you declare them, they way they can never have uninitialized values. This goes hand in hand with
always use the narrowest possible scope for variable declarations
So your first example, while no faster than the second, is still better.
And all of the people who chimed in telling him not to prematurely or micro optimize his code are wrong. It is never bad to know how costly various bits of code are. The very best programmers have a solid, almost unconcious, grasp of the cost of various strategies and take that into account automatically when they design. The way you become that programmer is to ask just this sort of question when you are a beginner.
¹ In fact, there is a small cost when each function allocates space for local variables, but that cost is the same regardless of how many local variables there are*.
*ok that's not really true, but the cost depends only on the total amount of space, not the number of variables.
Declaration takes no time at all.
The compiler will interpret that line as a notification that space for it will need to exist on the stack.
As others have already said, it shouldn't take any time. Therefore you need to make this decision based on other factors: what would make your code more readable and less prone to bugs. It's generally considered a good practice to declare a variable as close as possible to its usage (so you can see the declaration and usage in one go). If it's only used in the inner scope then just declare it inside that scope - forget about performance on this one.
Declaring variables does take time, as it results in machine language instructions that allocate the space for the variables on the stack. This is simply an increment of the stack pointer, which takes a tiny, but non-zero amount of time.
I believe your question is whether more time will be required (i.e. more stack increment operations) if the variable is declared inside the loop. The answer is no, since the stack is incremented once only for the loop block, not each time the loop is executed. So, there will be no difference in time either way, even if the loop executes zillions of zillions of times.
Disclaimer: Precisely what happens depends on your compiler, architecture, etc. But conceptually here's what's going on:
When you declare a variable within a method, it is allocated on the stack. Allocating something on the stack only involves bumping up the stack pointer by the size of the variable. So, for example, if SP represents the memory address of the top of the stack, declaring char x results in SP += 1 and int x results in SP += 4 (on a 32 bit machine).
When the function exits, the stack pointer is returned to where it was before your method was called. So deallocating everything is fast, too.
So, either way it's just an add, which takes the same amount of time regardless of the amount of data.
A smart compiler will combine several variable declarations into a single add.
When you declare a variable within a loop, in theory it could be changing the stack pointer on each iteration through the loop, but again, a smart compiler probably won't do that.
(A notable exception is C++, which does extra work because it needs to call constructors and destructors when the stack-allocated object is created or destroyed.)
I wouldn't care about a nanosecond here or there. Unless you need to access its value after the for loop ends, leave the variable inside the loop: it will be closer to the code that uses it (your code will be more readable), and its scope will be bounded by the loop itself (your code will be more elegant and less bug-prone).
I bet the compiled binary will be identical for both cases.
Variable declaration is turned into stack space reservation by the compiler. Now how does this work is entirely platform-dependent. On x86 and pretty much every popular architecture this is just a subtraction from the address of the stack frame and\or indexing addressing mode to access from the top of the stack. All these come with the cost of a simple subtraction\addition, which is really irrelevant.
Technically the second example is less efficient, because the declaration happens on every entry into the loop scope, i.e. on every loop iteration. However it is 99.99% chance that the stack space will be reserved only once.Even the assignment operation will be optimized away, although technically it should be done every loop iteration. Now in C++ this can get much worse, if the variable has a constructor which will then be run on every loop iteration.
And as a bottom line, you really should not worry about any of such issues without proper profiling. And even then there are much more valuable questions to ask yourself here, like "what is the most readable way to do this, what is easier to understand and maintain, etc.".

Resources