Reputation: 659
I am using Pelles C on Windows 8.1.
How to declare single global variable for a structure in C?
Code 1: it works but I do not want any other object of the same type to be created. If code 2 has problems then I will have to use this one.
Single.h
struct single{
int x;
};
extern struct single oneAndOnly;
void initSingle(void);
void printSingle(void);
Single.c
#include <stdio.h>
#include "Single.h"
struct single oneAndOnly;
void initSingle(void){
oneAndOnly.x = 10;
}
void printSingle(void){
printf("x = %d\n",oneAndOnly.x);
}
Main.c
#include "Single.h"
int main()
{
initSingle();
printSingle();
return 0;
}
Code 2: It works but I am not clear about the combination of declaring and defining a variable in a header file. Will it cause a problem? I get no error though.
Single.h
struct{
int x;
}oneAndOnly;
void initSingle(void);
void printSingle(void);
Single.c
#include <stdio.h>
#include "Single.h"
void initSingle(void){
oneAndOnly.x = 10;
}
void printSingle(void){
printf("x = %d\n",oneAndOnly.x);
}
Main.c is the same as in Code 1.
Can I use code 2 without any problem?
Can someone tell me why does code 2 work, when I and many others thought that it would not?
Thanks to everyone for all your comments and ideas and answers
Upvotes: 1
Views: 4872
Reputation: 20171
There is a third variant which might be of interest.
It "hides" the struct single
completely in Single.c
. Hence, no accidental access is possible.
Single.h
:
void initSingle(void);
void printSingle(void);
Single.c
:
#include <stdio.h>
#include "Single.h"
struct Single {
int x;
};
static struct Single oneAndOnly;
void initSingle(void)
{
oneAndOnly.x = 10;
}
void printSingle(void)
{
printf("x = %d\n", oneAndOnly.x);
}
main.c
:
#include "Single.h"
int main()
{
initSingle();
printSingle();
return 0;
}
Actually, this approach is similar to P__J__'s answer. I just was too slow to press the Send button.
I needed some time to realize that the solution in quest should prevent an (accidental) second variable of the type of oneAndOnly
.
"Hiding" the struct
in the C file with a static instance is probably the best one can have in C. Even the counter examples in melpomene's answer shouldn't work in this case.
If read/write access to the single instance is required, I would add something like "getter"/"setter" functions.
This reminded me to the Singleton pattern though I'm not sure if that is a legal usage for a non-OO language like C. Googling a bit, I found (as well) How to create a Singleton in C? which I find worth to mention.
I googled a bit concerning the actual question of OP whether her/his Code 2 is valid as well. I suspected something like a duplicated definition (may be, because I did too long in C++ in daily work).
Actually, I tried OP's Code 2 in Wandbox – no duplicate definition issue. Finally, I found Are the global variables extern by default or it is equivalent to declaring variable with extern in global? and came to the conclusion that Code 2 should be fine as well.
The limitation is that Code 2 allows only default initialization (filling with 0s if I remember right). As soon as an initializer is added, the compiler complains (as expected) as it's included multiple times.
Upvotes: 1
Reputation: 85897
None of your attempts will work in practice.
With e.g. gcc or clang I can just do
typeof(oneAndOnly) secondInstance;
gcc also supports
__auto_type secondInstance = oneAndOnly;
(not sure about clang).
Even if the compiler in question doesn't support these extensions, I can just copy/paste the anonymous struct declaration from the header.
That said, I don't see what preventing other objects of the same type buys you. It makes sense in Java to make the constructor private
because a constructor has behavior whose use you may want to restrict, but in C structs are just dumb collections of data.
Upvotes: 1
Reputation: 68059
You call the function in other compilation unit. It uses the global variable not your main program. So you do not even have to know the data structure and the variable, as you newer use any of them in your main program.
you can reduce it to :
void initSingle(void);
void printSingle(void);
int main()
{
initSingle();
printSingle();
return 0;
}
and
#include <stdio.h>
struct{
int x;
}oneAndOnly;
static struct single oneAndOnly;
void initSingle(void){
oneAndOnly.x = 10;
}
void printSingle(void){
printf("x = %d\n",oneAndOnly.x);
}
Upvotes: 1