typedef struct
{
int age;
int number;
} person;
static person self;//global declaration
person *Self(){
return &self;
}
I have been trying to understand the above similiar code which is used in a large code base any help would be appreciated.
- Why do we need such kind of function like above
Self()
function in C ? - What are the benefits ?
- Is there any drawbacks ?
CodePudding user response:
This specific snippet doesn't make much sense.
static
can be used as "poor man's private encapsulation", if an object is guaranteed to be a "singleton" - that is, only one instance exists and it is not accessed by multiple threads.
In this case the scope of the variable is reduced to the local .c file by static
.
And Self
act as a "getter" function. (As a singleton in a multi-threaded environment, you could place mutex/semaphores in the setter/getter functions, so that would be another use for them.)
However, while such a design might make sense in some cases, returning a non-const
qualifier pointer to a private variable is just as bad design as skipping private encapsulation and using globals/file scope variables.
To answer your questions based on the above:
- Why do we need such kind of function like above Self() function in C ?
If it returned a const
qualified pointer then it could make sense as a getter function. As it stands, it's just bloat and bad design though.
- What are the benefits ?
- Is there any drawbacks ?
As the code stands, no benefits, only drawbacks. It looks like a botched attempt to achieve private encapsulation.
To do proper, multi-instance private encapsulation in C, you wouldn't use static
but so-called "opaque types". Here is an example: How to do private encapsulation in C?
CodePudding user response:
This a way to have a global variable without using an actual global variable. This is certainly a pattern to avoid because now you can change the value of the struct from anywhere is this can lead to various bug hard to detect.
A cleaner way would be to return a copy of the struct or a pointer on a const variable to avoid being able to modify the variable from outside the module. If you need to modify the struct, create set/reset functions.
person Copy_of_self() {
person copy;
memcpy(©, &self, sizeof(copy)); // warning if you have tables or pointers in struct
return copy;
}
const person *Self() {
return (const person *)&self;
}
void Set_self(int age, int number) {
// Here you could add some checking on input values
self.age = age;
self.number = number;
}