I just need a way to restrict access of a global variable per my functions in C not C
static int global_int = 10;
int main(void)
{
global_int = 20; // allowed
}
void f()
{
global_int = 30; // global_int cannot be used here
}
What does I mean is, having more functions in a translation unit, I need to prevent some functions to access the global variable and allow some other function; instead of defining this variable in each function uses this variable.
CodePudding user response:
What you try to do is not possible. Instead, define those functions that are allowed to access the static global variable into a separate translation unit and define all the other functions in other translation unit(s).
So move f
into a separate file and keep main
in the same place as the definition of global.
There are other ways to hide informations in C, but in all cases it's just a convention that you establish for yourself and it's supposed you know what you are doing (this is the philosophy of C).
CodePudding user response:
"static
" (internal linkage) and "global" (external linkage) are mutually exclusive. You cannot have a "static global". You can however declare static
variables at file scope - that is, outside any function body. Such variables then get internal linkage and static storage duration.
A static
variable declared at file scope is accessible by every function residing in the same translation unit. Simply put: by any function present in the same .c file as the variable.
The correct solution is therefore to place main
in the same .c file as the variable and the function f
in a different .c file.
Example: Suppose you are designing a module called "stuff". stuff.h
is then your public interface, stuff.c
could contain the private implementation of some functions from the header and yet another file stuff_internal.c
could contain other function definitions. Both stuff.c
and stuff_internal.c
include stuff.h
but the static
file scope variable and all functions using it are placed in stuff_internal.c
.
For more advanced ways of achieving private encapsulation with multiple instances of an object in a thread-safe manner, see How to do private encapsulation in C?
CodePudding user response:
static and extern are separate qualifiers. static is only visible within the scope of the file. You can define main() and f() in separate files. You can define global_int as static in both files, they will be separate variables for the compiler.
static variables are allocated memory in data segment, not stack segment. If you want the variable to be visible across all files, declare them as extern.
CodePudding user response:
This problem is a symptom of the bad design, the correct approach is described in the other answers. However, it your options are limited you can use a following hack.
The problem can be addressed with preprocessor.
Just add a global_int
macro that expands to itself.
#define global_int global_int
There will no recursion because the expanded macro is always disabled the it is applied.
The when entering the "forbidded zone" just undefine this macro. optionally replace it with something else like global_int__guard
to get better diagnostics. And replace it back when leaving the forbidded zone.
#undef global_int
#define global_int global_int__guard
... code with no access to `global_int`
#undef global_int
#define global_int global_int
Any access toglobal_int
will cause a compilation error that global_int__guard
is undeclared.
You could use push/pop macro pragmas if your compiler supports it to make this process a bit more convenient.
CodePudding user response:
Your options include:
- Rewrite your program so you do not need such kludges. External variables should mostly be avoided.
- Rearrange your routines so the ones that should not see the variable are earlier:
void f(void)
{
// global_int is not visible here.
}
static int global_int = 10;
int main(void)
{
global_int = 20;
}
- If the variable is used only inside one function, declare it only inside that function:
int main(void)
{
static int global_int = 10;
global_int = 20;
}
void f(void)
{
// global_int is not visible here.
}
- Use macros as in tstanisl’s answer to conceal the name in some places.
- Split your functions across translation units according to the variables they should see.
- Hide variables by declaring the same name in an incompatible way in a new scope:
static int global_int = 10;
void f(void)
{
typedef struct foo global_int;
…
global_int = 20; // Gets an error because global_int is a type, not a variable.
}