Function name for returning a struct - c

I want to make a function in which I change an already existing struct. So the return value of that function should be a struct. If I want an int as return value I call the function "int example()" ... How do I call the function if I want to return a struct? Since "struct" is already taken — I already take "struct whatever" to create one.

If you want the function to modify an existing struct, you should pass the struct in by pointer:
void modify_thing(struct whatever *thing);
If you want to return a modified copy of the struct, you can return the struct by value:
struct whatever edit_thing(const struct whatever *input);
Note that it is usually more efficient to pass struct variables by pointer, rather than by value.

passing a struct by value will cause the compiler to establish 1 or more reserved areas in memory that can only be used for that function.
Each of those memory areas are manipulated by the compiler inserting calls to memcpy().
Much better to pass a pointer to the struct, then return a simple indication of success/failure of the struct update operation.

Related

Difference between modifying a function parameter and modifying a local variable

I saw a function that takes a list and a function pointer, and applies this
function to each element of the list.
ft_list.h
#ifndef LIST_H
#define LIST_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct s_list
{
struct s_list *next;
void *data;
} t_list;
#endif
ft_list_foreach.c
void ft_list_foreach(t_list *begin_list, void (*f) (void *))
{
t_list *curr;
curr = begin_list;
while (curr)
{
(*f)(curr->data);
curr = curr->next;
}
}
But why declare t_list *curr ? And not just increment begin_list until the end of the linked list(NULL) ?
Although in this case declaring a new variable which holds the pointer to the list makes no difference, I would say that this is a good practice to never mutate the function parameters, only when the function's nature requires to do so (i.e. when you have an inout parameter, like a buffer). This unwritten rule will save you from a lot of problems in future when dealing with more complex functions.
Consider just a simple case where you would need for some reason to also destroy and free the contents of this list after applying the f function. Of course, in this simple example you would easily spot the issue, but there are cases when this wouldn't be that obvious.
So, again, even though here it makes no difference, I strongly recommend to always write your functions using this pattern and this will avoid a lot of weird and unexpected issues.
A function can be designed to return a value, although there is technically no explicit need to so, when passing a pointer to an object
as argument to modify it in the function.
The reason for this is when you have a critical operation inside of the function, and there is an error with this operation, you can return a specific value to the caller to symbolize that an error occurred inside of the function.
I guess the author later (half) optimized the code of the function here as his/her first intent maybe was to add such a security mechanism or even prepare the code to maybe later add this if the function becomes more critical features.
It is a technique that you return the passed pointer, when the operations in the function were successful and f.e. NULL at an error.
Also a common technique is to reassign the passed pointer with the returned pointer value, although this is risky since you lose the reference in the caller completely if an error occurred in the called function.
Since you increment the pointer in the function, it would be not very good to return the incremented pointer as one might want to reassign the passed pointer with the return value, like:
int *p = //anything ;
p = foo(p);
You need to either store the passed pointer value inside of another separate pointer variable, increment this "copy" pointer and return the passed parameter variable
OR
store the value of the passed pointer into another local pointer variable, increment the parameter pointer and return the "copy" pointer.
Therefore it can make sense to use curr instead of begin_list to increment and use begin_list as return value at success.
Otherwise NULL if an error occurred.
Note that you need to change the return type from void to t_list * then.
Also:
Difference between modifying a function parameter and modifying a local variable
A parameter is a local variable.

Does scatter list pointer passed to sg_init_table() function need to be allocated before?

In a linux kernel PCI driver module.
We have a function to initialize dma scatter list:
sg_init_table(struct scatterlist *sg, unsigned int nents);
For the scatterlist pointor sg, should we allocate some memory for it, like using kcalloc;
or we just declare it like: struct scatterlist * sg and then pass it to sg_init_table?
Thx for advance.
There is no value to the caller in passing an uninitialized or invalid pointer value of any type to any function, other than simply to pad out the function's argument list with an argument of the expected type. The caller conveys no valid information to the function that way, and it provides no mechanism for the function to return any information. In particular, it does not provide a mechanism by which the called function can allocate memory on behalf of the caller. Pointers, like any other argument, are passed by value, so when a function modifies one of its parameters, that is not visible to the caller.
The function signature you present makes sense only for initializing an existing object of type struct scatterlist, or an array of such objects, or allocated memory intended to hold such an object or array. If that struct needs to be dynamically allocated then yes, the caller must perform the allocation and pass a pointer to the result.
Under some circumstances, however, it might be suitable for the caller to declare a local struct object, and to pass its address, something like this:
struct scatterlist sl;
sg_init_table(&sl, DEFAULT_NENTS);
or maybe
struct scatterlist sl[DEFAULT_NENTS];
sg_init_table(sl, DEFAULT_NENTS);
, depending on details of how sg_init_table() is meant to behave.
Similarly, it might be suitable to pass the address of a global struct. Do be aware of the lifetime of local objects -- unless declared static, local objects do not survive the end of the function call in which they were declared.

Struct points as parameter to function C

I have a few months that i started programming in C, but I now find myself with a doubt, for example, let see the next example code:
typedef struct
{
char *var1;
}myFooStruct;
myFooStruct struct1 [ 200 ];
my doubt is what would I get for **struct1, &struct1, *struct1, struct1,
as I passed the struct to a function that takes a two-dimenssion pointer ( **myFooStruct ), I have basic knowledge about pointers 1-but I find myself confused with pointers to structs and 2-how can I modify the struct if I passed it as at parameter to a function
If there is another similar question post it here please, I could not find anything alike, if you know some lecture I could read is welcome too, thank you very much!!
* is a dereference operator - think of it as meaning "the value contained at location xyz".
& is a reference operator - think of it as meaning "the location in memory of variable xyz".
Accordingly:
myFooStruct struct1 is a physical structure - this is the actual object.
&struct1 is equivalent to the location in memory of struct1 - this is usually an address (like 0xf0004782). You'll usually see this used when passing by reference (see Wikipedia for more info) or when assigning to a pointer (which literally points to a location in memory - get it?).
*struct1 dereferences struct1 - that is, it returns the value contained at location struct1. In the example you give, this is invalid, as struct1 is not a pointer to a location in memory.
**struct1 is tricky - it returns the value contained at the location that is contained within struct1. In other words: struct1 points to a certain location in memory. At that location is the address of another location in memory! Think of it as a scavenger hunt - you go to a location, find a clue, and follow that to another location.
As to how to access structs: think of a struct as a box. When you have the box in front of you, you simply need to open it up and look at what's inside. In C, we do this using the . operator:
char *my_var = struct1.var1
When you don't have the box in front of you - that is, you have a pointer to the struct - you need to access the location the box is at before you can look at what's inside. In C, we have a shortcut for this - the -> operator:
myFooStruct *pointer_to_struct1 = &struct1
char *my_var = pointer_to_struct1->var1
//NOTE: the previous line is equivalent to:
// char *my_var = (*pointer_to_struct1).var1
Way 1 Using dynamic memory allocation. Generally used in linked list and all..
If you want to modify the struct in another function. first declare a pointer to a struct.
myFooStruct* struct1;
Allot memory for the struct
struct1 = malloc(sizeof(myFooStruct));
Send the address to the function
func1(struct1);
Receive it and access it to modify in the function.
void func(myFooStruct* struct1)
{
(*struct1).member1 = ...; // whatever you wanna do
...
Way 2
Declare a struct.
myFooStruct struct1;
Send the address of the struct to the function
func1(&struct1);
Receive it and access it to modify in the function.
void func(myFooStruct* struct1)
{
(*struct1).member1 = ...; // whatever you wanna do
...
If you need to access myFooStruct from function, you can define single pointer: fn( myFooStruct * st ). The you call the function with fn( struct1 ) and change values st[N].var1 = .... Double pointer may be necessary if your object is pointer with allocated memory, not static array as yours.
struct1 is just a table and to be speciffic it's just pointer to a place in the memory.
*struct1 would be thing, that is pointed by struct1, so it's a first struct in a table of structs.
But **struct1 won't be any string. First of all you do not allocate memory for string and second string is member of this struct not struct itself. **struct is undefined behavior, nothing more.
&struct is a pointer to the table, so it's a pointer to the pointer, that points first struct in a table.
You have to decide on your own, what you want. If you want to pass table of your structs then the cleanest way would be:
void function(myFooStruct structTab[]);
1. You should pass a struct pointer to function to access struct inside it .
Declare a struct pointer -
myFooStruct *struct1;
Allocate memory for struct
And pass it to function which is declared as -
type fn(myFooStruct *struct1){
.....
}
Call this function like this -
fn(struct1);
Access struct member like this -struct->member1
2. You can also pass what you have declared right now.
myFooStruct struct1[ 200 ];
define function as -
type fn(myFooStruct struct1[]){
.....
}
Access struct members like this - struct[i].member1.

Returning struct in a c function

I have something like the folowing C code:
struct MyStruct MyFunction (something here)
{
struct MyStruct data;
//Some code here
return data;
}
would the returning value be a reference or a copy of the memory block for data?
Should MyFunction return struct MyStruct* (with the corresponding memory allocation) instead of struct MyStruct?
There is no such thing as a reference in C. So semantically speaking, you are returning a copy of the struct. However, the compiler may optimise this.
You cannot return the address of a local variable, as it goes out of scope when the function returns. You could return the address of something that you've just malloc-ed, but you'll need to make it clear that someone will need to free that pointer at some point.
It would return a copy. C is a pass-by-value language. Unless you specify that you are passing pointers around, structures get copied for assignments, return statements, and when used as function parameters.
It is returned as copy. BTW, you should not return it's reference because it has automatic storage duration ( i.e., data resides on stack ).
I have had problems with this (a function in a DLL returning a struct) and have investigated it. Returning a struct from a DLL to be used by people who might have a different compiler is not good practice, because of the following.
How this works depends on the implementation. Some implementations return small records in registers, but most get an invisible extra argument that points to a result struct in the local frame of the caller. On return, the pointer is used to copy data to the struct in the local frame of the caller. How this pointer is passed depends on the implementation again: as last argument, as first argument or as register.
As others said, returning references is not a good idea, as the struct you return might be in your local frame. I prefer functions that do not return such structs at all, but take a pointer to one and fill it up from inside the function.

Returning a local structure variable not dynamically allocated?

consider the following code:-
struct mystruct {
int data;
struct mystruct *next;
};
void myfunc ()
{
struct mystruct s1;
s1.data= 0;
s1.next = NULL;
myfunc2(&s1);
..
..
}
is it safe to pass the address of this local structure to other function.
Will this local structure be available for use outside the function or will it be already freed ?
It is safe to pass the address of a local variable to another function. The variable's life time extends to the end of the block (function or compound statement) in which it is declared.
It is not safe to return the address of a local variable or save a pointer to it and use it after the declaring function has returned.
Your wording is awkward in the question.
You can pass it to other functions by adress. It'll still be in valid scope.
But you can't return it by adress (which you are not doing here) outside of the function in which you declared it.
It will be available in myfunc2, but only as long as myfunc has not returned.
If myfunc2 somehow remembers this pointer and tries to use it after myfunc has returned, unpredictable things will happen because the stack has already been restored and the pointer will point to whatever garbage is there.

Resources