In C component selection, what is the benefit of structure-returning function? for example:
struct S {
int a, b;
} x;
Why is it that I can assign the above struct as a function as shown below, Is there any benefit of doing this?
extern struct S f(); /* Why is this neccesary? */
x = f(); /* Is this accurate */
Open my eyes on this guys.
It's just a function that happens to return a struct. There's nothing more to it than that. You wouldn't be surprised to see a function return an int, why be surprised when one returns a struct?
As an aside, the extern is superfluous here because that is the default storage class for functions.
It is useful so that you can return multiple values from a function.
For example, you can use it like this
struct Point {
int x;
int y;
};
struct Point getMousePos()
{
struct Point pos;
pos.x = 567;
pos.y = 343;
return pos;
}
int main()
{
struct Point mouse_pos = getMousePos();
printf("Mousepos %d,%d\n", mouse_pos.x, mouse_pos.y");
}
The function can be forward declared with extern (this would normally be done in a header file), so that other functions know its prototype i.e. its parameters and return type, even if the function is itself defined in another file.
If you get a copy of a struct instead of a pointer to it, you know that you never have to worry about free()ing it, or whether there are any data races where one thread is writing to the struct while another reads from it, or whether the pointer returned by the function will be invalidated by some action that might be outside of your control.
Related
I'm practicing c and I want to return data of a struct to access it within an other location.
Let's say I have something like this:
typedef struct
{
int8 x;
u64 y;
u32 z;
} myData_t;
myData_t myData_g;
/*Setter*/
void WritemyData(const myData_t* data)
{
myData_g = *data;
}
How can I return the data which are stored within a global variable to be read within an other location. Can I not just do something like:
/*Getter*/
myData_t GettmyData(void)
{
return myData_g;
}
Would be thankful for any information!
First of all, for things like this consider making the "global" a private variable instead, by adding static myData_t myData_g;. Now nobody outside this .c file can access it intentionally/by accident.
As for your function GettmyData, it will work fine. However, passing/returning structs by value is considered bad practice since it involves making a full copy of the struct on the stack, which may be slow and take up unnecessary memory temporarily.
This might be better idea might be:
void get_my_data (myData_t* obj)
{
*obj = myData_g;
}
Here you have to document that the caller should allocate the variable pointed at by obj on the caller side.
In our code base, I encountered some C code that I am not able to understand why it works.
Pretty sure implements some pattern found on the internet. Ideally this code should emulate some object-oriented pattern from C++, and it is used to create queues.
Here is (part of) the code for the declaration (.h) of the queue module:
struct Queue_t
{
uint8_t Queue[MAX_QUEUE_SIZE];
uint32_t Head;
uint32_t Tail;
uint16_t Counter;
Queue_return_t (*Push)(struct Queue_t * Queue, uint8_t * NewElement, uint16_t ElementSize);
Queue_return_t (*Pop)(struct Queue_t * Queue, Queue_Element_t *RetElement);
Queue_return_t (*Flush)(struct Queue_t * Queue);
};
extern const struct QueueClass {
struct Queue_t (*new)( void );
} Queue_t;
struct Queue_t new( void );
Here is (part of) the code for the implementation (.c) of the queue module:
struct Queue_t new( void )
{
struct Queue_t NewQueue;
[...]
NewQueue.Push = &QueueManager_Push;
NewQueue.Pop = &QueueManager_Pop;
NewQueue.Flush = &QueueManager_Flush;
return NewQueue;
}
const struct QueueClass Queue_t={.new=&new};
then the usage in the code is the following:
struct Queue_t Output_Queue;
Output_Queue = Queue_t.new();
[...]
RetQueue = Output_Queue.Pop(&Output_Queue,Output_Queue_elem);
Now, we switched to a more straightforward queue implementation.
Still I am not able to grasp what is going on in this code.
As stated in the title, my problem is in the "new" function, where a struct Queue_t is declared in a local scope and then returned.
As further information, in the project that used this "queue" module there was no dynamic memory allocation, hence no heap, free or malloc.
Everything worked really smooth, I would expect the code to crash as soon as the stack for the referenced object is freed and the pointer to the structure is accessed.
Also, the compiler used was IAR and is not complaining (this code was used on a uC).
Maybe the const qualifier is involved?
Any hint on what is going on?
It is perfectly legal to return a value declared inside a function. The problem only arises if you return a pointer to a value declared inside a function, and then try to access it.
The new() function you show is equivalent to:
int foo(void) {
int a = 123;
return a;
}
There is no problem here, you're returning a value which is copied to the destination when doing:
int x;
x = foo(); // copy happens here
Using x after this is not accessing the (now vanished) stack of foo, since x is defined outside foo and was copied when the function returned.
Doing this with a struct is no different, a struct is still treated as a single value, the only real difference is in the generated machine code, since copying a structure takes more effort (you need to copy each field).
The problem, again, only arises when you return a pointer to a locally defined variable and try using it outside:
int *foo(void) {
int a = 123;
return &a; // never do this!
}
int main(void) {
int *x;
x = foo();
return *x; // OUCH!
}
Now dereferencing x (both for reading and for writing) means trying to access the (now vanished) stack of foo, and this is of course a problem.
The following link says that structs defined in main don't have the scope to be called by functions because they are local so you should define your structs globally. However with variables, it's preferred to declare variables locally and pass to functions with pointers instead of declaring global variables.
Is there a way in pure C using pointers etc to pass a struct defined in main to a function? If you don't mind, please use the example program to demonstrate the method. Thanks.
where to declare structures, inside main() or outside main()?
This code works but is not what I want. I want to define the structure within main. Is this possible?
#include <stdio.h>
#include <SDL2/SDL.h>
void function();
struct hexColour
{
Uint32 red;
}hc;
int main(void)
{
hc.red = 0xFFFF0000;
function(hc);
return 0;
}
void function(struct hexColour hc)
{
printf("red is %x\n", hc.red);
}
What I want is:
int main(void)
{
struct hexColour
{
Uint32 red;
}hc;
hc.red = 0xFFFF0000;
function(hc);
return 0;
}
First of all you should really use proper prototypes that matched the function definitions.
Secondly, your example do pass a structure into the local variable hc in the function.
When function is running there are two distinct and separate structures in memory: The one in the main function, and the local in the function function.
To cover my bases, here are two answers for two other question that maybe is asked:
You want to define the structure itself inside the main function, and then be able to use it in other functions.
Something like
int main(void)
{
struct hexColor
{
uint32_t white;
// Other members omitted
};
struct hexColour hc;
hc.white = 0xff;
func(hc); // Assume declaration exist
}
void func(struct hexColour my_colour)
{
printf("White is %u\n", my_colour.white);
}
This is not possible. The structure hexColour is defined inside the main function only. No other function can use that structure. It doesn't matter if you pass a pointer or not, the structure hexColour still will only exist inside the main function only.
Emulate pass-by-reference by passing a pointer to a structure object. Like
struct hexColor
{
uint32_t white;
// Other members omitted
};
int main(void)
{
struct hexColour hc;
hc.white = 0xff;
// Assume declaration of function exists
func(&hc); // Emulate pass-by-reference by passing a pointer to a variable
}
void func(struct hexColour *colourPointer)
{
colourPointer->white = 0x00;
}
This is possible, because then the structure hexColour exists outside the main function, in the global scope. All functions declared and defined after the structure definition may use the structure and its members.
If you pass by value a copy is made (expensive, modifications are not reflected outside). If you want to pass a pointer to a struct just go with, but this doesn't mean you are passing a struct by reference (C doesn't have references), you are passing a pointer to a struct by value instead.
void function(struct hexColour* hc) {
printf("red is %x", hc->red);
}
int main() {
...
functon(&hc);
...
}
See:
Signature of the function changes from struct hexColor to struct hexColor* so that you are passing a pointer (by value)
To access field of the struct when dealing with pointers you use -> instead that .
You need to take the address to the struct when invoking the function, function(hc) becomes function(&hc)
Now since you are passing the address the the struct any modification is done to the real value.
You seem to have understood your linked question and its answers incompletely. You write,
The following link says that structs defined in main don't have the
scope to be called by functions because they are local so you should
define your structs globally.
The ambiguity here is between struct types, such as your struct hexColour, and objects having those types, such as your hc. Both struct types and struct objects should be declared so that they are in scope at all the places where they are needed, but that plays out differently for these two different kinds of entities and in various different situations.
However with variables, it's preferred to declare variables locally
and pass by reference instead of declaring global variables.
It is usually best to use block-scope variables instead of file-scope variables, yes, but C has only pass by value, not pass by reference. There are plenty of circumstances where it is advantageous to pass pointers (by value) instead of the objects to which they point, and this is close to pass by reference, but there is certainly no rule or general practice that passing pointers is universally better than passing the objects to which they point.
Is there
a way in pure C using pointers etc to pass a local struct to a
function?
Both the caller and the callee have to agree about the type of each argument, and there are many ways to achieve this. But there are some conventions that have grown up along with C for how to approach problems such as these in an effective way. Large among them is this:
Any function and any non-builtin type that is to be used in multiple translation units should be declared in a header file, and that header included in every translation unit that needs it.
That's a generalization of the rule you couched in terms of "global" definitions. Example:
colour.h
#ifndef COLOUR_H
#define COLOUR_H
struct hexColour {
Uint32 white;
Uint32 black;
Uint32 red;
Uint32 pink;
Uint32 grey;
}; // Note that only the type is declared here, not any objects
void function(struct hexColour hc);
#endif
Note that the declaration of type struct hexColour appears before the declaration of function function that has a parameter of that type.
You can then use those types and functions with appropriate locality, for example:
main.c:
#include "colour.h"
int main(void) {
struct hexColour hc = {
.white = 0xFFFFFFFF, .black = 0xFF000000, .red = 0xFFFF0000,
.pink = 0xFFFF9999, .grey = 0xFFA0A0A0 };
function(hc);
return 0;
}
void function(struct hexColour hc) {
printf("red is %x\n", hc.red);
}
Note that the declaration of function that forms part of its definition here matches the declaration in the header. That definition function() could as easily be defined in a different source file, instead, as long as the caller has the header file to tell it how that function is declared. You can #include coulour.h into as many different source files as needed.
Do note, however, that in this case, the struct is passed by value. That's well-defined and perfectly acceptable, but inasmuch as the function receives only a copy, it cannot effect changes to the caller's original copy. If you wanted the function to be able to do that, then you would need to pass a pointer to the struct (by value) instead of the struct itself:
void function(struct hexColour *hc) {
// ...
}
int main(void) {
// ...
function(&hc);
// ...
}
You can take a locally-defined struct and pass it to another function:
void f1(struct s);
int main()
{
struct s s1;
f1(s1);
}
You can take a locally-defined struct and pass a pointer to it to another function:
void f2(struct s *);
int main()
{
struct s s2;
f2(&s2);
}
You can return a locally-defined struct:
struct s f3()
{
struct s ret;
/* ... */
return ret;
}
You can not return a pointer to a locally-defined struct:
struct s *f4()
{
struct s ret;
/* ... */
return &ret; /* WRONG */
}
If you declare a struct within a function, it is not a global variable, so you can not refer to it in another function to which you did not pass the structure or a pointer:
void f5();
int main()
{
struct s s1;
f5();
}
void f5()
{
int x = s1.field; /* WRONG */
}
Finally, if you declare the struct type itself inside a function, you end up with a struct which you can't properly refer to elsewhere:
void f1(struct s);
int main()
{
struct s { int a, b; } s1;
f1(s1);
}
void f1(struct s arg) /* error: this struct s might not be the same as the previous one */
{
int x = arg.b; /* error: compiler might not know that struct s contains a and b */
}
Looked at the previous answers. Suggest you wrap your mind around the 'C' difference between a declaration and a definition. Note that earlier versions of 'C' would NOT allow passing a copy of a structure on the stack, only a pointer to a struct..
I am currently using the out of date open BGI library for C as that is what my uni wants us to do but I can't figure out how to use this function.
extern void getmousestate(g_mousestate *state);
Definition:
void getmousestate(g_mousestate * state)
{
CHECK_GRAPHCS_INITED
state->x = sharedStruct->mouseX;
state->y = sharedStruct->mouseY;
state->buttons = sharedStruct->mouseButton;
}
g_mousestate Definition:
typedef struct mousestate {
int x, y;
int buttons;
}g_mousestate;
sharedStruct definition:
static SHARED_STRUCT * sharedStruct;
SHARED_STRUCT Definition:
typedef struct
{
int mouseX, mouseY;
int mouseButton;
int keyCode;
int keyLetter;
int visualPage;
} SHARED_STRUCT;
The sort of thing I was trying to do to call:
g_mousestate *a;
getmousestate(a->x);
But I don't know what to initialize a to...
I assumed this function could tell me what position the mouse is in and what buttons are being pressed etc, but I can't figure out how to call the function properly. Very much a beginner here, any help would be appreciated.
OK, beginner, let's start. You want to do:
g_mousestate *a;
getmousestate(a->x);
to get the x-position of the mouse. First note that you have declared a as a pointer, but no memory has been allocated for it (it points to nothing yet). So first you must have memory for the g_mousestate object:
g_mousestate a;
getmousestate(&a);
Now a is no longer a pointer but an object and you pass a pointer to the getmousestate function by taking the address of a with the & operator ("address-of").
You need to do no more since, if you look at the definition of the function, you see that all members are filled in by it.
Is it safe to return a struct with array data member in C?
Something like
struct my_str {
int v[5];
};
struct my_str ret_stupid() {
struct my_str rval;
/*do something..*/
return rval;
}
I don't know why... I'm a bit puzzled. (I've tried and it does work). Is there some standard explaining how this operation actually is performed? I mean the mechanism of struct return and assignment too could be useful to understand better.
Is it safe to return a struct with array data member in C?
Yes.
struct are copied bit-wise. Bit-wise copying a struct that has an array as a member makes sure that the copy of struct has a copy of the array too.
Structures are a lot like arrays.
They can contain variables of any kind.
Their addresses will be sorted stacked as long as you leave no gaps or invoke the preprocessor directive #pragma pack
"Is it safe", depends of the code hiding there..
/do something../
But in general - yes. This is just a function of type struct my_str and has to return struct my_str
What the structure contains - doesn't matter. Still safe to use.
You can return a structure from a function without any problems. It's a well-defined part of the language. You can pass structures to functions as well - a structure is exactly the same as any built-in type for purposes of parameter passing, return values, and assignment.
Here's an example
#include <stdio.h>
int func(int x)
{
int r = x;
return r;
}
int main(void)
{
int x = 12;
int y = func(x);
printf("%d\n", y);
return 0;
}
If it weren't for the array member, the return would be an "rvalue", a value that is just a copy of the value that you have inside the return expression. If you have
struct toto {
double a;
};
struct toto g(void) {
struct toto retval = { 0.0 };
...
return retval;
}
int main(void) {
printf("%g\n", g().a);
}
The argument of the printf call sees a copy of the variable retval that is used inside the function. g().a calls the function and uses the .a field of the return value.
This return value is and
entity that is not an object but only lives because of its "value", called rvalue in the C jargon. It only can be found on the RHS of an assignment, thus the "r" in "rvalue".
The case that you are giving is actually specially treated, because a "value" is not sufficient for all use cases of the array. So this generates a so-called "object with temporary lifetime". This is needed because if you'd do ret_stupid().v[2] the [] operator wants to have a pointer, and a pointer can only point to an object, not a value.
These objects only "live" inside the expression that contains the function call, and even though they are not const qualified you are not allowed to modify them.
So all in all, this is a corner case of C, and you shouldn't abuse it.