Is it bad practice to instantiate C struct object as global variable? - c

Here is an example code, struct A is declared and then it's instance "instanceOfA" is defined inside main, so it become local variable and to access it in other functions I should pass it as an argument. On the other hand struct B is declared and it's instance defined as global variable that allows me to use "instanceOfB" anywhere I need it, directly instead of passing it around as an argument. The only thing I should worry about now is that some function may overwrite "instanceOfA" identifier right? since it's variables (a,b,c) already in it's own "namespace". So is it a bad practice to define struct object as global variable? What would you do?
Sorry for my poor English.
struct A {
int a,b,c;
};
struct B {
int a,b,c;
} instanceOfB;
int main(void) {
struct A instanceOfA;
instanceOfA.a = 5;
instanceOfB.a = 10;
}

I'm not sure what is the question about exactly, but here are some thoughts.
instanceOfB is a global variable, right? So, it is an evil that should be avoided if not strictly necessary.
On the contrary, struct A instanceOfA; inside function body looks fine for me, though we usually move types from struct namespace to global namespace by using typedef struct idiom to reduce typing.

Yes, indeed, it is very bad practice to define anything as a global variable, not just a struct.
Yes, you will need to be passing it as a parameter. That's actually good, not bad.
It means that every single individual piece of code (function) in your program will only be able to modify what it is being given to modify, and not whatever it pleases.

Related

Class approximation in C - Is this witchcraft or technically acceptable?

I need to do a large Project in C and C only, without external librairies (except for SDL).
I started looking for ways to do some kind of class in C, what led me to that :
typedef void (*voidFunction)(void);
typedef struct{
int id;
voidFunction printId;
} Object;
Object *new_Object(int id){
Object *newObject = malloc(sizeof(Object));
newObject->id = id;
void printId(){
static Object *this = NULL;
if(!this) this = newObject;
printf("%d\n", this->id);
};
newObject->printId = printId;
return newObject;
}
int main(){
Object *object = new_Object(5);
object->printId();
object->id++;
object->printId();
return 0;
}
Output of main :
5
6
So this works, but does it seems reasonable ?
Should I expect a backlash if I use this kind of architecture for a big project? Maybe I'm typing out of my allocated memory without realizing it?
Techniques for implementing polymorphism in C are long established, check this answer for instance https://stackoverflow.com/a/351745/4433969
Your implementation seems to be broken. Nested functions are non-standard extension. I also have doubts about static this variable.
The non-standard nested function printId is used incorrectly. In GCC documentation Nested functions one can read:
If you try to call the nested function through its address after the containing function exits, all hell breaks loose.
The nested functions are called via trampolines, the small pieces of executable code located on stack. This code is invalidated when the parent function exits.
Though as the functions does not refer to any local variables the code will likely work. The compiler will likely avoid trampolines but rather create a kind-of "anonymous" static function.
The idiomatic solution should take a pointer to "Object" as an argument rather than use a static variable.
typedef struct Object {
int id;
void (*printId)(struct Object*);
} Object;
void printId(Object *this){
printf("%d\n", this->id);
};
...
object->printId(object);
There are advantages for using a struct to organize data for bulk processing. However, the only advantage of using the function pointer rather than calling the function directly would be:
To allow the function pointer to point to different functions having the same type for different instances of the object.
To hide the "member" function definition from the linker. For example, the function printId could be declared as static within the module containing the definition for "constructor" new_Object.

Expected Type qualifier before static ? [duplicate]

#include<stdio.h>
struct str
{
static int a ;
int b ;
} s ;
int main()
{
static int p , k ;
printf("%d %d",sizeof(p),sizeof(s));
getchar();
return 0;
}
above code is giving errors . But if I redefine the first member of the structure to 'int' rather than 'static int' then it runs fine . Why static members are not allowed in the structure and what is its significance ?
There's simply no such feature in C language. And there's no meaningful conceptual framework for such feature in C.
You see, in C++ terms, there's only one relevant difference between a static member variable and an ordinary global variable: the scope in which its name is declared and the corresponding naming syntax. A global variable could be called a, while a static member of the class would be called SomeClass::a. Besides scoped naming, there are no other differences. (I deliberately ignore other C++-specific features, like access control, since they don't exist in C and this question is really about C.)
In C language a struct type does not introduce its own scope. There's no such naming syntax as SomeStruct::a in C language. For this reason there's simply no reason to have static members in structs. You can declare a global variable instead and achieve the same effect. Call your global variable str_a to convey the intent to "associate" it with struct str and just think of that variable as a pseudo-static member of struct str.
Formally speaking, one could do it the same way in C++, i.e. completely ignore this feature of C++ language and use global functions and variables instead of static function and variables inside classes. However, by doing that one would forsake all member access control features of C++. And these features are really worth having. C language has no access control features, meaning that in C one loses [almost] nothing.
The language just doesn't allow it. There's no deeper reason other than that it's not part of the design. You can always achieve the same behaviour with a separate global variable like this:
struct str
{
int b;
} s;
int str_a;
Note that it would be something entirely different to have a non-static int a; inside your struct, which would be a distinct subelement of every object of type struct str.
(Note also that in C++, a language evolved from C, static class members do exist and behave exactly like the workaround I described above, only that the name of the global variable is tightly associated to the name of the class.)
A static modifier is to declare your variable in the global scope in your file and a static modifier in a function creates a variable with a persistant value limited to the scope of this functions. And you can not share the value of this integer between your instances of your struct.
This is not and cannot be supported in C ;)
Why do you want to use a static member in a struct? maybe there is (there must be) a better soluation.
You have good answers here: http://cboard.cprogramming.com/c-programming/123691-static-variable-structure.html
generally speaking you don't have any gain from declaring it static, but if you still wish to it , you may migrate to c++ or declare the whole struct as static.
No, not in C. I believe C++ can do this and it means there is one copy of a that is shared amongst all instances of the struct str structure.
If you want to do something similar in C, you have a few options (there may be more, I just can't think of them at the moment).
The first is to break out the common variable with something like:
int struct_str_static_a;
struct str {
int b;
} s;
That way, there is only one copy of a shared by all instances of the structure - each instance still gets its own copy of b.
A slight modification to that is to introduce a pointer to that common variable and initialise the pointer:
int struct_str_static_a;
struct str {
int *pA;
int b;
} s;
:
s.pA = &struct_str_static_a;
Then you can use *(s.pA) where before you would have used s.a. Because every instance of struct str has its own pA pointer that points to a single a, that gives you a similar effect. However, it's a torturous road to follow.
The third option is to get yourself on the next ISO C working group and put this forward as a change to the language. However, that's going to require a fair bit of effort from yourself for the next ten years or so, probably not worth the effort :-)

Terminology when Initializing C Structures

This will be an easy question but googling around does not seem to provide me with an answer. The way I understand it in C we have two ways to initialize a foo object, when foo is a structure. Look at the code below for an example
typedef struct foo
{
int var1;
int var2;
char* var3;
}foo;
//initializes and allocates a foo
foo* foo_init1(int v1,int v2,const char* v3)
{
if(..some checks..)
return 0;
foo* ret = malloc(sizeof(foo));
ret->var1 = v1;
ret->var2 = v2;
ret-var3 = malloc(strlen(v3)+1);
strcpy(ret->var3,v3);
return ret;
}
// initializes foo by ... what? How do we call this method of initialization?
char foo_init2(foo* ret,int v1,int v2, const char* v3)
{
//do some checks and return false
if(...some checks..)
return false//;assume you defined true and false in a header file as 1 and 0 respectively
ret->var1 = v1;
ret->var1 = v1;
ret->var2 = v2;
ret-var3 = malloc(strlen(v3)+1);
strcpy(ret->var3,v3);
return true;
}
So my question is this. How do we refer in C to these different initializing methods? The first returns an initialized pointer to foo so it's easy to use if you want a foo object on the heap like that:
foo* f1 = foo_init1(10,20,"hello");
But the second requires a foo .. what? Look at the code below.
foo f1;
foo_init2(&f1,10,20,"hello");
So the second method makes it easy to initialize an object on the stack but how do you call it? This is basically my question, how to refer to the second method of initialization.
The first one allocates and initializes a pointer to foo.
The second one initializes a foo by ... what? Reference?
As a bonus question, how do you guys work when coding in C? Do you determine the usage of the object you are making and by that determine if you should have an initializing function of type1 , or 2 or even both of them?
I am not sure if there are any well defined nomenclature for the two methods,
In the first method the function dynamically allocates a structure and assigns values to the members,
while in second the structure is allocated before the function and the function then just assigns values to the members.
Do you determine the usage of the object you are making and by that determine if you should have an initializing function of type1 , or 2 or even both of them?
Selecting first or second method depends on a important difference:
The first method is preferred when you need to pass the returned structure across scopes, the memory on heap has to be explicitly freed untill which the data prevails while in Second method the data on stack gets removed once the scope of the passed object ends.
Since none of the people in the comments took up on the offer to turn their comments into an answer I am forced to reply to my own question.
Well basically a possible answer would be that as AIs states there is no specific naming convention. Of course whatever naming method is used, it should be:
Consistent across all of the project/s for clarity's sake
Recognizable by other programmers as a function that does what it is actually doing.
To achieve that there were some great recommendations in the comments. For when a foo object is:
Passed for initialization inside the function: foo_init
Allocated inside the function and a pointer returned: foo_alloc, foo_make , foo_new
All of the above are clear I suppose but what is most accurately describes what is happening in the functions would be foo_init and foo_alloc.
Personally I really dislike the _alloc solution because I don't like how it looks in my code so I decided to add the verb _create instead of alloc after the function to denote what it's doing.
But well what the answer boils down to I guess is personal preference. All should be okay and acceptable as long as the functionality of the function is made clear by reading its name.

Struct Scope Access

Hi this a continuation of a previous question I asked however I wasn't registered then and thus cannot edit the question. Anyways I have a struct
typedef struct
{
char input[100][100];
int count;
char name;
int startTime;
}INPUT;
extern INPUT *global;
this is within the header file. A stackoverflow member suggested that in my source file i use
INPUT global_[N], *global = global_;
to declare and initialise it which worked fine(as in I was able to store and print information out of the struct from within that method) however when I go to use the variable in other parts of my code it seems that the variable is out of scope?
I declare and use the variable global_ in a method called readFile and i'm trying to access the same information in main via *global.
Can this be done?
Thanks
Chee
extern INPUT *global;
This declares a global variable named global.
INPUT global_[N], *global = global_;
This defines an array global_ and a variable global. Depending on where this definition occurs (at function scope, or in a namespace, a class, or a function), global might or might not define the same object that's referred to by the declaration of global.

C variables scope in struct

I've faced three separate situations in C lately that I would assistance on:
My C code has a global variable:
int ref_buf; //declared in a header file
In a function definition I use the same name as a parameter:
void fun(int ref_buf, param2, param3)
{
}
Will it overwrite the originally defined global variable and will it cause bugs?
Can I declare a static variable in a C data structure like so?:
struct my
{
int a;
static int b;
};
Does it work? Is there any specific situation where one would need it?
Can I initialize a individual structure variable as follows:
struct my
{
int a;
int b = 4;
};
Question 1
All references to ref_buf in that function will bind to the parameter and not the global variable.
Question 2
This is not legal in C but is legal in C++. The keyword static in C can only be used on file scope variables or on locals.
Question 3
No this is not legal in C (or C++). You will need to create a factory method to handle this.
my create_my() {
my m;
m.b = 4;
return m;
}
On Q3: GCC allows you to initialize a struct like this (as required by the C99 standard):
struct
{
int a;
int b;
} my = { .b = 4 };
GCC doc on designated initializers
1a) The local and global variables are separate entities, and so the local one won't overwrite the global. However, the global one won't be accessible inside the function (see also notes below).
1b) It not actually incorrect, but it is guaranteed to cause confusion, and confusion causes bugs, so it's best to use different names for each.
2) No, that's not legal C. You can however make the whole struct static.
3) No. You do it like this:
struct my
{
int a;
int b;
} = {0, 4};
Note 1: Variables should be declared in .c files, not .h files. If you need to make a variable accessible in multiple files, put an extern declaration in the header file.
Note 2: Avoid global variables if at all possible.
Question 1:
I think the variable declared in the local scope takes precidence, it shouldn't overwrite it but in the scope that the variable is declared it will be used instead.
That is assuming that it compiles.
On Q1:
Do not declare variables in a header file. If you include that header file in two source files and compile the source files together, you've got problems. Maybe your linker will get you out of them, maybe not.
If you really need global variables, and this happens a lot less than typical beginners think, put something like extern int ref_buf; in the header file, and int ref_buf; in a source file. That means there is one ref_buf, and all other source files will be able to find it.
The function parameter is essentially a new variable with the same name, and all references in the function will be to it. You will not be able to access the global variable from within that function. The function creates an inner scope, and variables declared in an inner scope are different from those in an outer one. This is potentially confusing, and makes it easy to create bugs, so having variables of the same name and different scopes is generally discouraged. (Variables of the same name in different struct definitions are usually not confusing, since you have to specify what struct contains the variable.)
The compiler will compile the function, but a good compiler will issue a warning message. If it refuses to compile because of one variable shadowing another of the same name, it isn't a real C compiler.
1) Local variables always take precedence e.g.
int ref = 10;
void fun(int ref)
{
printf("\n%d\n", ref);
}
int main()
{
fun(252);
return 0;
}
shows: 252
Qs 2 and 3 won't work in C.
Yes, it will technically overwrite, but a good compiler will warn you about this situation, and you will have "warnings = errors" on when you compile, so this won't actually compile.
Not needed, since the "my" struct is already declared as static, and it is therefore declared for the entire struct. This allocates the memory for the entire struct, so there is no need to say "take part of the struct which is already static and make it static".
No, not in the definition, but you can when you create an "instance", something like:
struct my MY =
{
{0, 4}
};

Resources