Reputation: 57
Lets say I have two (or more) c functions func1()
and func2()
both requiring a buffer variable int buff
. If both functions are kept in separate files, func1.c and func2.c, How do I make it so that buff
is accessible to only func1()
and func2()
and not to the calling routine(or any other routine).
Here is an example setup:
file func1.c:
/*func1.c*/
static int buff;
int *func1(int x)
{
buff = x;
return &buff;
}
file func2.c:
/*func2.c*/
static int buff;
int *func2(int x)
{
buff = x;
return &buff;
}
header header.h:
/*header for func1.c and func2.c*/
//multiple inclusion guard not present.
int *func1(int);
int *func2(int);
file main.c:
#include<stdio.h>
#include"header.h"
int main()
{
int *ptr;
ptr = func1(1);
printf("&buff = %p , buff = %d\n", ptr, *ptr);
ptr = func2(2);
printf("&buff = %p , buff = %d\n", ptr, *ptr);
return 0;
}
As expected, the output shows different memory locations for buff.
&buff = 0x55b8fd3f0034 , buff = 1
&buff = 0x55b8fd3f0038 , buff = 2
But I need only one copy buff, not more.
I could of course, put both functions in the same file, and define buff
as static int but then I would lose the ability to compile the functions separately.
If I put int buff
in a separate buff.c and declare it extern in func1.c and func2.c, but then it would be easily accessible by the calling routine(main in this case).
Basically, I need to create a library of functions that work on the same external object, that is accessible only to them. The calling routine may not need all the functions, so I do not want to put them in a single file and create unused code. But there must be only one copy of the object.
Please help on how I could do the same, if it is achievable.
Upvotes: 1
Views: 482
Reputation: 47952
One typical approach to this problem is to give the global variable a name that begins with _
.
That is, in func1.c you might write
int _mylib_buff;
And then in func2.c, of course, you'd have
extern int _mylib_buff;
Now, of course, in this case, _mylib_buff
is technically an ordinary global variable. It's not truly "private" at all. But global variables beginning with _
are private "by convention", and I'd say this works okay in practice. But, obviously, there's nothing preventing some other source file from cheating and peeking at the nominally-private variable, and there's no way in Standard C to prevent one from doing so.
The other complication is that some identifiers beginning with _
are reserved to the implementation, and you're not supposed to use them in your own code. (That is, components of the implementation -- like your C compiler and C library -- have semi-global variables they're trying to hide from you, and they're typically using a leading _
to achieve this, also.) I'm pretty sure the rules say it's okay for you to define a global variable beginning with a leading underscore followed by a lower-case letter, but the rules are somewhat complicated, and I can never remember all the nuances. See questions 1.9 and 1.29 in the C FAQ list.
Upvotes: 2
Reputation: 222856
The C standard does not provide a way to do this. It is usually done using features of compilers and linkers beyond the C standard. Here is an example using Apple’s developer tools on macOS. For options suitable to your environment, you should specify the build tools and versions you are using, such as whether you are using Apple tools, GNU tools, Microsoft tools, or something else.
With this in a.c
:
#include <stdio.h>
int x = 123;
void a(void)
{
printf("In a.c, x is %d.\n", x);
}
and this in b.c
:
#include <stdio.h>
extern int x;
void b(void)
{
printf("In b.c, x is %d.\n", x);
}
we compile the source files to object modules:
clang -c a.c b.c
and then link them to a new object module r.o
while requesting that the symbol x
(_x
in the linker view) not be exported:
ld -r -o r.o -unexported_symbol _x a.o b.o
Then, if we have another source file c.c
that attempts to use x
:
#include <stdio.h>
extern int x;
extern void a(void);
extern void b(void);
int main(void)
{
a();
b();
printf("In c.c, x is %d.\n", x);
}
attempting to build an executable with it using clang -o c c.c r.o
yields:
Undefined symbols for architecture x86_64: "_x", referenced from: _main in c-139a35.o ld: symbol(s) not found for architecture x86_64
However, if we remove the two lines in c.c
that refer to x
, the build succeeds, and the program prints:
In a.c, x is 123. In b.c, x is 123.
Upvotes: 3
Reputation: 67546
You need to define the non-static variable in one of the files for example:
int buff;
int *func1(int x)
{
buff = x;
return &buff;
}
in the header file declare it as extern
:
/*header for func1.c and func2.c*/
//multiple inclusion guard not present.
extern int buff;
int *func1(int);
int *func2(int);
Include it in all other files:
/*func2.c*/
#include "header.h"
int *func1(int x)
{
buff = x;
return &buff;
}
If you do not want variable to be visible you need to create function which will get and set the "hidden" variable.
typedef enum
{
GET,
SET,
REF,
}OP_t;
#define CREATE(type, name) type getset##name(OP_t oper, type val, type **ref) \
{\
static type buff;\
switch(oper)\
{\
case GET:\
return buff;\
case SET:\
buff = val;\
break;\
case REF:\
if(ref) *ref = &buff;\
break;\
}\
return 0;\
}\
#define HEAD(type, name) type getset##name(OP_t oper, type val, type **ref)
#define GETVAL(name) getset##name(GET, 0, NULL)
#define SETVAL(name,val) getset##name(SET, val, NULL)
#define GETREF(name,ref) getset##name(REF, 0, ref)
Upvotes: 0
Reputation: 44274
The answer is: It's not possible.
C has no way of saying "this variable may be used by source file x, y, z and not by any other sources files".
So if you want buff
to be "private" to a number of functions, you'll have to put those functions in the same source file.
Upvotes: 1