Direct invocation vs indirect invocation in C - c

I am new to C and I was reading about how pointers "point" to the address of another variable. So I have tried indirect invocation and direct invocation and received the same results (as any C/C++ developer could have predicted). This is what I did:
int cost;
int *cost_ptr;
int main()
{
cost_ptr = &cost; //assign pointer to cost
cost = 100; //intialize cost with a value
printf("\nDirect Access: %d", cost);
cost = 0; //reset the value
*cost_ptr = 100;
printf("\nIndirect Access: %d", *cost_ptr);
//some code here
return 0; //1
}
So I am wondering if indirect invocation with pointers has any advantages over direct invocation or vice-versa? Some advantages/disadvantages could include speed, amount of memory consumed performing the operation (most likely the same but I just wanted to put that out there), safeness (like dangling pointers) , good programming practice, etc.
1Funny thing, I am using the GNU C Compiler (gcc) and it still compiles without the return statement and everything is as expected. Maybe because the C++ compiler will automatically insert the return statement if you forget.

Indirect and direct invocation are used in different places. In your sample the direct invocation is prefered. Some reasons to use pointers:
When passing a large data structure to a function one can passa pointer instead of copying the whole data structure.
When you want a function to be able to modify a variable in the calling function you have to pass a pointer to the original variable. If you pass it by value the called function will just modify a copy.
When you don't know exactly which value you want to pass at compile time, you can set a pointer to the right value during runtime.
When dynamically allocating a block of memory you have to use pointers, since the storage location is not known until runtime.

The pointer notation involves two memory fetches (or one fetch and one write) where the direct invocation involves one.
Since memory accesses are slow (compared to computation in registers; fast compared to access on disk), the pointer access will slow things down.
However, there are times when only a pointer allows you to do what you need. Don't get hung up on the difference and do use pointers when you need them. But avoid pointers when they are not necessary.

In the "printf(..., *cost) case, the value of "cost" is copied to the stack. While trivial in this instance, imagine if you were calling a different function and "cost_ptr" pointed to a multi-megabyte data structure.

Related

When should I pass or return a struct by value?

A struct can be either passed/returned by value or passed/returned by reference (via a pointer) in C.
The general consensus seems to be that the former can be applied to small structs without penalty in most cases. See Is there any case for which returning a structure directly is good practice? and Are there any downsides to passing structs by value in C, rather than passing a pointer?
And that avoiding a dereference can be beneficial from both a speed and clarity perspective. But what counts as small? I think we can all agree that this is a small struct:
struct Point { int x, y; };
That we can pass by value with relative impunity:
struct Point sum(struct Point a, struct Point b) {
return struct Point { .x = a.x + b.x, .y = a.y + b.y };
}
And that Linux's task_struct is a large struct:
https://github.com/torvalds/linux/blob/b953c0d234bc72e8489d3bf51a276c5c4ec85345/include/linux/sched.h#L1292-1727
That we'd want to avoid putting on the stack at all costs (especially with those 8K kernel mode stacks!). But what's about middling ones? I assume structs smaller than a register are fine. But what about these?
typedef struct _mx_node_t mx_node_t;
typedef struct _mx_edge_t mx_edge_t;
struct _mx_edge_t {
char symbol;
size_t next;
};
struct _mx_node_t {
size_t id;
mx_edge_t edge[2];
int action;
};
What is the best rule of thumb for determining whether a struct is small enough that it's safe to pass it around by value (short of extenuating circumstances such as some deep recursion)?
Lastly please don't tell me that I need to profile. I'm asking for a heuristic to use when I'm too lazy/it's not worth it to investigate further.
EDIT: I have two followup questions based on the answers so far:
What if the struct is actually smaller than a pointer to it?
What if a shallow copy is the desired behavior (the called function will perform a shallow copy anyway)?
EDIT: Not sure why this got marked as a possible duplicate as I actually link the other question in my question. I'm asking for clarification on what constitutes a small struct and am well aware that most of the time structs should be passed by reference.
On small embedded architectures (8/16-bitters) -- always pass by pointer, as non-trivial structures don't fit into such tiny registers, and those machines are generally register-starved as well.
On PC-like architectures (32 and 64 bit processors) -- passing a structure by value is OK provided sizeof(mystruct_t) <= 2*sizeof(mystruct_t*) and the function does not have many (usually more than 3 machine words' worth of) other arguments. Under these circumstances, a typical optimizing compiler will pass/return the structure in a register or register pair. However, on x86-32, this advice should be taken with a hefty grain of salt, due to the extraordinary register pressure a x86-32 compiler must deal with -- passing a pointer may still be faster due to reduced register spilling and filling.
Returning a structure by value on PC-likes, on the other hand, follows the same rule, save for the fact that when a structure is returned by pointer, the structure to be filled out should be passed in by pointer as well -- otherwise, the callee and the caller are stuck having to agree on how to manage the memory for that structure.
My experience, nearly 40 years of real-time embedded, last 20 using C; is that the best way is to pass a pointer.
In either case the address of the struct needs to be loaded, then the offset for the field of interest needs to be calculated...
When passing the whole struct, if it is not passed by reference,
then
it is not placed on the stack
it is copied, usually by a hidden call to memcpy()
it is copied to a section of memory that is now 'reserved'
and unavailable to any other part of the program.
Similar considerations exist for when a struct is returned by value.
However, "small" structs,
that can be completely held in a working register to two
are passed in those registers
especially if certain levels of optimization are used
in the compile statement.
The details of what is considered 'small'
depend on the compiler and the
underlying hardware architecture.
Since the argument-passing part of the question is already answered, I'll focus on the returning part.
The best thing to do IMO is to not return structs or pointers to structs at all, but to pass a pointer to the 'result struct' to the function.
void sum(struct Point* result, struct Point* a, struct Point* b);
This has the following advantages:
The result struct can live either on the stack or on the heap, at the caller's discretion.
There are no ownership problems, as it is clear that the caller is responsible for allocating and freeing the result struct.
The structure could even be longer than what is needed, or be embedded in a larger struct.
How a struct is passed to or from a function depends on the application binary interface (ABI) and the procedure call standard (PCS, sometimes included in the ABI) for your target platform (CPU/OS, for some platforms there may be more than one version).
If the PCS actually allows to pass a struct in registers, this not only depends on its size, but also on its position in the argument list and the types of preceeding arguments. ARM-PCS (AAPCS) for instance packs arguments into the first 4 registers until they are full and passes further data onto the stack, even if that means an argument is split (all simplified, if interested: the documents are free for download from ARM).
For structs returned, if they are not passed through registers, most PCS allocate the space on the stack by the caller and pass a pointer to the struct to the callee (implicit variant). This is identical to a local variable in the caller and passing the pointer explicitly - for the callee. However, for the implicit variant, the result has to be copied to another struct, as there is no way to get a reference to the implicitly allocated struct.
Some PCS might do the same for argument structs, others just use the same mechanisms as for scalars. In any way, you defer such optimizations until you really know you need them. Also read the PCS of your target platform. Remember, that your code might perform even worse on a different platform.
Note: passing a struct through a global temp is not used by modern PCS, as it is not thread-safe. For some small microcontroller architectures, this might be different, however. Mostly if they only have a small stack (S08) or restricted features (PIC). But for these most times structs are not passed in registers, either, and pass-by-pointer is strongly recommended.
If it is just for immutability of the original: pass a const mystruct *ptr. Unless you cast away the const that will give a warning at least when writing to the struct. The pointer itself can also be constant: const mystruct * const ptr.
So: No rule of thumb; it depends on too many factors.
Really the best rule of thumb, when it comes to passing a struct as argument to a function by reference vs by value, is to avoid passing it by value.
The risks almost always outweigh the benefits.
For the sake of completeness I'll point out that when passing/returning a struct by value a few things happen:
all the structure's members are copied on the stack
if returning a struct by value, again, all members are copied from the function's stack memory to a new memory location.
the operation is error prone - if the structure's members are pointers a common error is to assume you are safe to pass the parameter by value, since you are operating on pointers - this can cause very difficult to spot bugs.
if your function modifies the value of the input parameters and your inputs are struct variables, passed by value, you have to remember to ALWAYS return a struct variable by value (I've seen this one quite a few times). Which means double the time copying the structure members.
Now getting to what small enough means in terms of size of the struct - so that it's 'worth' passing it by value, that would depend on a few things:
the calling convention: what does the compiler automatically save on the stack when calling that function(usually it's the content of a few registers). If your structure members can be copied on the stack taking advantage of this mechanism than there is no penalty.
the structure member's data type: if the registers of your machine are 16 bits and your structure's members data type is 64 bit, it obviously won't fit in one registers so multiple operations will have to be performed just for one copy.
the number of registers your machine actually has: assuming you have a structure with only one member, a char (8bit). That should cause the same overhead when passing the parameter by value or by reference (in theory). But there is potentially one other danger. If your architecture has separate data and address registers, the parameter passed by value will take up one data register and the parameter passed by reference will take up one address register. Passing the parameter by value puts pressure on the data registers which are usually used more than the address registers. And this may cause spills on the stack.
Bottom line - it's very difficult to say when it's ok to pass a struct by value. It's safer to just not do it :)
Note: reasons to do so one way or the other overlap.
When to pass/return by value:
The object is a fundamental type like int, double, pointer.
A binary copy of the object must be made - and object is not large.
Speed is important and passing by value is faster.
The object is conceptually a smallish numeric
struct quaternion {
long double i,j,k;
}
struct pixel {
uint16_t r,g,b;
}
struct money {
intmax_t;
int exponent;
}
When to use a pointer to the object
Unsure if value or a pointer to value is better - so this is the default choice.
The object is large.
Speed is important and passing by a pointer to the object is faster.
Stack usage is critical. (Strictly this may favor by value in some cases)
Modifications to the passed object are needed.
Object needs memory management.
struct mystring {
char *s;
size_t length;
size_t size;
}
Notes: Recall that in C, nothing is truly passed by reference. Even passing a pointer is passed by value, as the value of the pointer is copied and passed.
I prefer passing numbers, be they int or pixel by value as it is conceptually easier to understand code. Passing numerics by address is conceptual a bit more difficult. With larger numeric objects, it may be faster to pass by address.
Objects having their address passed may use restrict to inform the function the objects do not overlap.
On a typical PC, performance should not be an issue even for fairly large structures (many dozens of bytes). Consequently other criteria are important, especially semantics: Do you indeed want to work on a copy? Or on the same object, e.g. when manipulating linked lists? The guideline should be to express the desired semantics with the most appropriate language construct in order to make the code readable and maintainable.
That said, if there is any performance impact it may not be as clear as one would think.
Memcpy is fast, and memory locality (which is good for the stack) may be more important than data size: The copying may all happen in the cache, if you pass and return a struct by value on the stack. Also, return value optimization should avoid redundant copying of local variables to be returned (which naive compilers did 20 or 30 years ago).
Passing pointers around introduces aliases to memory locations which then cannot be cached as efficiently any longer. Modern languages are often more value-oriented because all data is isolated from side effects which improves the compiler's ability to optimize.
The bottom line is yes, unless you run into problems feel free to pass by value if it is more convenient or appropriate. It may even be faster.
We do not pass structs by value, neither we use naked pointers (gasp!) all the time and everywhere. Example.
ERR_HANDLE mx_multiply ( MX_HANDLE result, MX_HANDLE left, MX_HANDLE right ) ;
result left and right are instances of the same (struct) type for 2D matrix
multiply is some other error (struct) type
'handle' is the address of the struct on the memory 'slab' pre-allocated for the instances of the same types
is this safe? Very. Is this slow? A bit slower vs naked pointers.
in an abstract way a set of data values passed to a function is a structure by value, albeit undeclared as such.
you can declare a function as a structure, in some cases requiring a type definition. when you do this everything is on the stack. and that is the problem. by putting your data values on the stack it becomes vulnerable to over writing if a function or sub is called with parameters before you utilize or copy the data elsewhere. it is best to use pointers and classes.

Why Use Pointers in C?

I'm still wondering why in C you can't simply set something to be another thing using plain variables. A variable itself is a pointer to data, is it not? So why make pointers point to the data in the variable when you can simply use the original variable? Is it to access specific bits (or bytes, I guess) of data within said variable?
I'm sure it's logical, however I have never fully grasped the concept and when reading code seeing *pointers always throws me off.
One common place where pointers are helpful is when you are writing functions. Functions take their arguments 'by value', which means that they get a copy of what is passed in and if a function assigns a new value to one of its arguments that will not affect the caller. This means that you couldn't write a "doubling" function like this:
void doubling(int x)
{
x = x * 2;
}
This makes sense because otherwise what would the program do if you called doubling like this:
doubling(5);
Pointers provide a tool for solving this problem because they let you write functions that take the address of a variable, for example:
void doubling2(int *x)
{
(*x) = (*x) * 2;
}
The function above takes the address of an integer as its argument. The one line in the function body dereferences that address twice: on the left-hand side of the equal sign we are storing into that address and on the right-hand side we are getting the integer value from that address and then multiply it by 2. The end result is that the value found at that address is now doubled.
As an aside, when we want to call this new function we can't pass in a literal value (e.g. doubling2(5)) as it won't compile because we are not properly giving the function an address. One way to give it an address would look like this:
int a = 5;
doubling2(&a);
The end result of this would be that our variable a would contain 10.
A variable itself is a pointer to data
No, it is not. A variable represents an object, an lvalue. The concept of lvalue is fundamentally different from the concept of a pointer. You seem to be mixing the two.
In C it is not possible to "rebind" an lvalue to make it "point" to a different location in memory. The binding between lvalues and their memory locations is determined and fixed at compile time. It is not always 100% specific (e.g. absolute location of a local variable is not known at compile time), but it is sufficiently specific to make it non-user-adjustable at run time.
The whole idea of a pointer is that its value is generally determined at run time and can be made to point to different memory locations at run time.
No, a variable is not a pointer to data. If you declare two integers with int x, y;, then there is no way to make x and y refer to the same thing; they are separate.
Whenever you read or write from a variable, your computer has to somehow determine the exact location of that variable in your computer's memory. Your computer will look at the code you wrote and use that to determine where the variable is. A pointer can represent the situation where the location is not known at the time when you compile your code; the exact address is only computed later when you actually run your code.
If you weren't allowed to use pointers or arrays, every line of code you write would have to access specific variables that are known at compile time. You couldn't write a general piece of code that reads and writes from different places in memory that are specified by the caller.
Note: You can also use arrays with a variable index to access variables whose location is not known at compile time, but arrays are mostly just syntactical sugar for pointers. You can think about all array operations in terms of pointer operations instead. Arrays are not as flexible as pointers.
Another caveat: As AnT points out, the location of local variables is usually on the stack, so they are a type of variable where the location isn't known at compile time. But the only reason that the stack works for storing local variables in a reentrant function is that your compiler implements hidden pointers called the stack pointer and/or frame pointer, and functions use these pointers to find out which part of memory holds their arguments and local variables. Pointers are so useful that the compiler actually uses them behind your back without telling you.
Another reason: C was designed to build operating systems and lots of low level code that deals with hardware. Every piece of hardware exposes its interface by means of registers, and on nearly all architectures, registers are mapped into the CPU memory space, and they have not to be in the same address always (thanks to jumper settings, PnP, autoconfig, and so on)
So the OS writer, while writing a driver for instance, needs a way to deal with what seems memory locations, only that they don't refer RAM cells.
Pointers serve to this purpose by allowing the OS writer to specify what memory location he or she wants to access to.

How should I pass a struct in a function?

I am confused because I haven't written C in a while. In C++, we would pass them as references, in order not to copy the whole struct. Does this apply to C too? Should we pass them as pointers, even if we don't want to modify them, in order to avoid copying?
In other words, for a function that checks if two structs are equal, we better do
int equal(MyRecord* a, MyRecord* b);
and decrease a bit the readability (because of pointers)
or
int equal(MyRecord a, MyRecord b);
will have the same performance?
Often, passing pointers is faster - and you'll call equal(&r1, &r2) where r1 and r2 are local struct variables. You might declare the formals to be const pointers to a const structure (this could help the optimizing compiler to generate more efficient code). You might also use the restrict keyword (if you are sure you'll never call your equal with two identical pointers, e.g. equal(&r1,&r1), i.e. without pointer aliasing).
However, some particular ABIs and calling conventions may mandate particular processing for some few particular structures. For example, the x86-64 ABI for Linux (and Unix SVR4) says that a struct with two pointers or integral values will be returned thru two registers. This is usually faster than modifying a memory zone with its pointer in a register. YMMV.
So to know what is faster, you really should benchmark. However, passing a large-enough struct (e.g. with at least 4 integral or pointer fields) by value is almost always slower than passing a pointer to it.
BTW, what really matters on current desktop and laptop processors is the CPU cache. Keeping frequently used data inside L1 or L2 cache will increase performance. See also this.
What is faster massively depends on the size of the struct and it’s use inside the called function.
If your struct is not larger than a pointer, passing by value is the best choice (less or equal amount of data needs to be copied).
If your struct is larger than a pointer, it heavily depends on the kind of access taking place inside the called function (and appearantly also on ABI specifics). If many random accesses are made to the struct, it may be faster to pass by value, even though it’s larger than a pointer, because of the pointer indirection taking place inside the function.
All in all, you have to profile to figure out what’s faster, if your struct is larger than a pointer.
Passing pointers is faster, for the reasons you say yourself.
Actually, I find C more readable than C++ in this case: by passing a pointer in the call, you acknowledge that your paramters might get changed by the called function. With C++ references, you can't immediately say that by seeing only the call, you also have to check out the called function prototype to see if it uses references.

C programming: the cost of passing by value

I am learning C and get confused about something I read online.
At http://www.cs.bu.edu/teaching/c/stack/array/
I could read:
Let's look at the functions that determine emptiness and fullness.
Now, it's not necessary to pass a stack by reference to these
functions, since they do not change the stack. So, we could prototype
them as:
int StackIsEmpty(stackT stack);
int StackIsFull(stackT stack);
However, then some of the stack functions would take pointers (e.g.,
we need them for StackInit(), etc.) and some would not. It is more
consistent to just pass stacks by reference (with a pointer) all the
time
(I am not showing the code for what a stackT is, it is just a dynamic array)
From my (maybe limited) understanding, the disadvantage of passing by value is that the data is duplicated in the stack memory of the function. Since a stackT might be big, passing by value rather than pointer would be time consuming.
Do I get it right or am I still not clear with the basics ?
Correct, if you pass something "large" by value that item is copied onto the stack.
Passing a pointer to the data avoids the copy.
It is doubtful that the performance difference will be meaningful in most real-world applications, unless "large" is actually "huge" (which in turn may overflow the stack).
You are correct. Passing by value causes the program to copy, in the entirety, all of the data in that parameter. If it's only one or two ints, no problem, but copying multiple kilobytes is very expensive. Passing by reference only copies the pointer.
However, you must watch out for changing the data pointed at by the pointer and then expecting to return to it unchanged. C++ has passing by "const reference", which is like a guarantee that the data will not be changed, but C does not.

Function parameter or local variable

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.

Resources