struct example{
int a;
int b;
};
in main.c
I can write to this struct in main.c as follows
struct example obj;
obj.a=12;
obj.b=13;
Is there a way that I can directly write to the global memory location of this struct, so that the values can be accessed anywhere across the program?
Two ways:
You can take it address and pass it as a parameters to the functions that needs to access this data
&obj
Or, use a global:
Outside of any function, write struct example obj;
And in a header declare:
struct example {
int a;
int b;
};
extern struct example obj;
Edit: Reading this issue might be a good idea: How do I use extern to share variables between source files?
There are two ways to accomplish this:
1.
Create a header file that contains the following statement:
/* header.h */
extern struct example obj;
Add the following definition to one and only one source file:
/* source.c */
struct example obj;
Any source file that needs direct access to obj should include this header file.
/* otherFile.c */
#include "header.h"
void fun(void)
{
obj.a = 12;
obj.b = 13;
}
2.
Create getter/setter functions:
/* source.c */
static struct example obj;
void set(const struct example * const pExample)
{
if(pExample)
memcpy(&obj, pExample, sizeof(obj));
}
void get(struct example * const pExample)
{
if(pExample)
memcpy(pExample, &obj, sizeof(obj));
}
/* otherFile.c */
void fun(void)
{
struct example temp = {.a = 12, .b = 13};
set(&temp);
get(&temp);
}
With this method, obj can be defined as static.
You can initialize it with a brace initializer, as in:
struct example obj = {12,13};
You could also declare a pointer to it, as in:
struct example* myPtr = &obj;
int new_variable = myPtr->a;
and then use that pointer to access the data members. I hope this addresses your question.
Related
I am having trouble putting together some code in which I wish to have the following:
Have a header file myHeader.h in which I create a type struct myStruct with members int number1, int number2 and int number3. This file would also contain a "getter" prototype for getting the address of each of the members in a struct instance.
A translation unit (file.c) in which I declare a static instance of struct myStruct, i.e. static struct myStruct myStructInstance. This translation unit defines the "getter" functions (I will illustrate with a code example at the end of the post).
Another header file anotherHeader.h in which I wish to - now this is a tricky bit that's causing problems for me - get the addresses of each of the members of a static structure and use them for something.
Here's an example to show what I am talking about.
myHeader.h
struct myStruct{
int number1;
int number2;
int number3;
};
int* get_number1(void);
int* get_number2(void);
int* get_number3(void);
file.c
#include <myHeader.h>
static struct myStruct myStructInstance = {
.number1 = 0,
.number2 = 0,
.number3 = 0
};
int* get_number1(void){
struct myStruct* ptr_myStructInstance = &(myStructInstance);
int* number1Address = &(ptr_myStructInstance->number1);
return number1Address;
}
int* get_number2(void){
struct myStruct* ptr_myStructInstance = &(myStructInstance);
int* number2Address = &(ptr_pfcVariables->number2);
return number2Address;
}
int* get_number3(void){
struct myStruct* ptr_myStructInstance = &(myStructInstance);
int* number3Address = &(ptr_myStructInstance->number3);
return number3Address;
}
anotherHeader.h
#include <myHeader.h>
int* pNumber1 = get_number1();
int* pNumber2 = get_number2();
int* pNumber3 = get_number3();
The problem is that the code shown above throws "initializer element is not constant" error in anotherHeader.h. I've read a few answers as to why we cannot use non-constant expressions when initializing variables with static storage duration, however I do not understand how this relates to my code.
I've read a few answers as to why we cannot use non-constant expressions when initializing variables with static storage duration, however I do not understand how this relates to my code.
A function call is a non-constant expression.
int* pNumber1 = get_number1();
The above code is trying to initialize a global variable with a non-constant expression.
You simply can't call code in the global scope.
However, you could easily accomplish the same thing as what you appear to be trying to do by simply extending myHeader.h with:
extern int *pNumber1, *pNumber2, *pNumber3;
and then allocating and initializing these in file.c with:
int *pNumber1 = &myStructInstance.number1,
*pNumber2 = &myStructInstance.number2,
*pNumber3 = &myStructInstance.number3;
I am new to C, and I am used to Java OOP. I have to use struct as holder for my global variables, that the system will write to/read from constantly.
I have 3 different types of variables in the struct, and I am not sure if that can cause a problem.
Also - do I need to declare the struct in the header file, in order to use it other C file ?
What will be the fastest and better way to access the variables from that struct in the different functions ? // The functions using these variables are in the same C file.
Here is the struct itself, that I made:
struct Data
{
double percentage_Height = 0;
double speed_Height = 0;
double time_Height = 0;
int distance_Height = 0;
double percentage_Distance = 0;
double speed_Distance = 0;
double time_Distance = 0;
int distance_Distance = 0;
uint16_t valueSpeed = 0;
double speedOfMotor = 0;
int tilt = 0;
};
and an example of a function that should use some of the fields of the struct:
int getHeight()
{
percentage_Height = getIncline()/90.0;
speed_Height = db_speed_sensor();
time_Height = 0.000027; // [h] , 100ms
distance_Height=0;
if (percentage_Height == 0)
{
percentage_Height = 1;
}
distance_Height = speed_Height * time_Height * percentage_Height * 100;
return distance_Height;
}
so what will be the best way to access these struct fields, instead of writing just the global vars?
EDIT: it is a real-time operating system, so tasks (smth like threads) will be accessing the data in the struct. I don't know if that makes any changes...
Define a global variable of type Data and access its members wherever you want.
struct Data GlobalData;
int getHeight()
{
GlobalData.percentage_Height = getIncline()/90.0;
GlobalData.speed_Height = db_speed_sensor();
....
}
If you want to use this in multiple files, better to define the structure in header file.
You have to declare the structure in a header file.
If an instance of this structure will be in the global scope, you have to define this instance in the global scope like this:
struct Data gData;
int getHeight()
{
gData.percentage_Height = getIncline()/90.0;
...
}
If your instance will be used only in the functions which are declared in the same file, you should define your variable like this:
static struct Data gData;
int getHeight()
{
gData.percentage_Height = getIncline()/90.0;
...
}
The keyword "static" means your variable is in the file scope (only visible in the file)
Yes, you should define the struct in a file and need to include it for its usage in other files. different datatypes in structure won't have any issue.
You can define functions separately to access the structure members and to process it. so that you don't need to repeat code. [ as like you did getHeight() ]. you can define those functions *inline*
to improve performance. (fastest way to access?) [only if the function is simple and (small in size)]
even you can use MACROS.
Use typedef for convenience.
typedef struct { ... } DATA;
so that code can be simplified. instead of writting
struct Data *s; simply put DATA *s;
you should use
s->structmember to process it.
Everyone has advised you to use a global structure. I would just like to add that, as you mentioned, all the functions accessing this structure are in one file, you should also declare a structure as static so that global structure will be limited file scope.
What will be the fastest and better way to access the variables from that struct in the different functions ? // The functions using these variables are in the same C file.
Using a pointer to that struct.
Example:
int getHeight(struct Data *data)
{
data->percentage_Height = getIncline()/90.0;
data->speed_Height = db_speed_sensor();
data->time_Height = 0.000027; // [h] , 100ms
data->distance_Height=0;
if (data->percentage_Height == 0)
{
data->percentage_Height = 1;
}
data->distance_Height = data->speed_Height * data->time_Height * data->percentage_Height * 100;
return data->distance_Height;
}
int main(int argc, char *argv[])
{
struct Data data;
load_data(&data); // function to initialize data
distance_Height = getHeight(&data);
return distance_Height;
}
Let the compiler decides when to inline those functions to improve performance, you should be worried about the readability and organization of your code.
Also - do I need to declare the struct in the header file, in order to use it other C file ?
If you want to direct access its members in other sources, you need to define it in a header, but you could just declare that you have that struct in you C, and create function to access the values of you struct. In this case you could define the struct only in the source file, and declare it in a header or any other source files you need this declaration.
Example:
file1:
#include <stdlib.h>
struct my_struct_s {
int value;
};
struct my_struct_s *create_my_struct(void)
{
return malloc(sizeof(struct my_struct_s));
}
void destroy_my_struct(struct my_struct_s *my_struct)
{
free(my_struct);
}
void set_my_struct(struct my_struct_s *my_struct, int value)
{
my_struct->value = value;
}
int get_my_struct(struct my_struct_s *my_struct)
{
return my_struct->value;
}
file 2:
#include <stdio.h>
#include <string.h>
struct my_struct_s;
struct my_struct_s *create_my_struct(void);
void destroy_my_struct(struct my_struct_s *my_struct);
void set_my_struct(struct my_struct_s *my_struct, int value);
int get_my_struct(struct my_struct_s *my_struct);
int main() {
struct my_struct_s *my_struct;
my_struct = create_my_struct();
set_my_struct(my_struct, 10);
printf("my_struct value = %d\n", get_my_struct(my_struct));
destroy_my_struct(my_struct);
return 0;
}
It would be better to have a header with the declarations needed to access the struct of file1, and include this header in file2, just made it this way to show you that it is possible, and maybe give you a clue about the difference between definition and declaration
A struct can hold any variety of types, no problem with how many variables you have in there as long as you have the memory for them.
You can declare a struct in a header file, but you will need to initialise it somewhere.
For example if you initialise it in a source file that is not your main and you still want to use it there, you will have to declare it in the main file with the keyword extern. Let me demonstrate:
file.h - a struct Foo is defined here
file.c - an instance of Foo named foo is initialised here with some values.
main.c - we want to use it here. In order to do that we put a statement for example right after the includes that reads extern struct Foo foo;
Or you can plain add file.h to your main.c file and just initialise it there.
Normally a struct variable is accessed like this: name_of_struct.member, e.g. struct.int_member = 42.
If you have a pointer to a struct and you try to modify the struct via the pointer there are two ways of doing this:
The more popular way:
ptr_to_struct->member = 42;
Or a more typical way for other types, but rather unusual in this case (at least for one level of dereference):
*ptr_to_struct.member = 42;
I would recommend that you pass the struct as an argument to the functions modifying it. Don't just use it as a plain global.
Here is the case. In the file "fileA.c" I have
typedef struct MY_STRUCT
{
int A;
int B;
int C;
}MY_STRUCT;
MY_STRUCT Data;
/* Function */
int function(MY_STRUCT *params)
{
int varA, varB, varC;
varA = params->A;
varB = params->B;
varC = params->C;
}
And I need to fill the struct elements from other routine, for instance, "fileB.c" which contains the following:
extern MY_STRUCT Data;
int function(MY_STRUCT *params);
/* Function */
void userMain(void)
{
Data.A = 1254;
Data.B = 5426;
Data.C = 1236;
function(&Data);
}
But I'm getting the error:
"[Error] fileB.c E208: syntax error - token ";" inserted before "Data"
And whe I cross probe the error the compiler take me to the declaration "extern MY_STRUCT Data;"
So my question is how do I accomplish this functionality? I mean, how do I fill the elements of the structure from another function in another file different from the file where I declared the struct?
When the compiler is compiling fileB.c, it doesn't know about the typedef that you've defined in fileA.c. So in fileB.c, MY_STRUCT is an unknown type.
You should move the typedef to a common header, and include it in fileA.c and fileB.c.
Elaborating a bit on #pb2q answer:
Create a filea.h file with (omitting the defines and stuff):
struct MY_STRUCT
{
(blah blah blah ...)
};
extern MY_STRUCT Data;
This will declare the struct and tell whoever wants to know that the variable is declared in another file. Then put in filea.c the following lines
#include "filea.h" // near the top
(...)
MY_STRUCT Data; // Somewhere meaningful
This will actually declare the variable Data. Finally, in file "fileb.c" type
#include "filea.h"
that allows you to use the variable Data.
In C, you can define structures to hold an assortment of variables;
typedef struct {
float sp;
float K; // interactive form - for display only
float Ti; // values are based in seconds
float Td;
} pid_data_t;
But lets say that K, Ti, and Td should never be set publicly, and should only be used for storing the values after they have been manipulated. So, I want these values not to be updated by;
pid_data_t = pid_data;
pid_data.K = 10; // no good! changing K should be done via a function
I want them to be set via a function;
int8_t pid_set_pid_params(float new_K_dash, float new_Ti_dash,
float new_Td_dash)
{
… // perform lots of things
pid_data->K = new_K_dash;
pid_data->Ti = new_Ti_dash;
pid_data->Td = new_Td_dash;
}
Any thoughts on this? I know C++ uses like a get/set property, but was wondering what people might do on C.
Your public interface should only offer an opaque pointer (maybe DATA*, or data_handle), as well as handler functions create_data(), set_data_value(), read_data_value(), free_data(), etc., which operate on the opaque pointer.
Much like FILE*.
Just don't give your clients the internal header files :-)
// library.h
typedef struct data_t * data_handle;
data_handle create_data();
void free_data(data_handle);
Private implementation (don't ship):
#include "library.h"
struct data_t
{
/* ... */
};
data_handle create_data() { return malloc(sizeof(struct data_t)); }
void free_data(data_handle h) { free(h); }
/* etc. etc. */
in C, by convention....
for OO C like this...
I'd have a pid_data_create(&data) // initializes your struct
and pid_data_set_proportional_gain(&data, 0.1);
etc...
so basically achieving a C++ ish class... prefix all functions with the "class" / "struct" name and always pass the struct * as the first parameter.
also, it should store function pointers for polymorphisim, and you shouldn't call those function pointers directly, again, have a function that takes your struct as a parameter, and then the can make the function pointer call (can check for nulls, fake inheritance/virtual functions, and other stuff)
The canonical way to do this is by using a combination of opaque pointers and public structs, along with allocators, getters and setters for the private elements. About along these lines:
foo.h
typedef struct Foo {
/* public elements */
} Foo;
Foo *new_Foo(void);
void Foo_something_opaque(Foo* foo);
foo.c
#include "foo.h"
typedef struct Private_Foo_ {
struct Foo foo;
/* private elements */
} Private_Foo_;
Foo *new_Foo(void)
{
Private_Foo_ *foo = malloc(sizeof(Private_Foo_));
/* initialize private and public elements */
return (Foo*) foo;
}
void Foo_something_opaque(Foo *foo)
{
Private_Foo_ *priv_foo = (Private_Foo_*) foo;
/* do something */
}
This woks, because C guarantees, that the address of a struct variable always is equal to the address of the very first struct element. We can use this to have a Private_Foo_ struct, containing a public Foo at the beginning, giving out pointers to the whole thing, with the compilation units not having access to the Private_Foo_ struct defintion just seeing some memory without any context.
It should be noted that C++ works quite similar behind the curtains.
Update
As KereekSB pointed out, this will break if used in a array.
I say: Then don't make Foo f[], however tempting, but make an arrays of pointers to Foo: Foo *f[].
If one really insists on using it in arrays do the following:
foo_private.h
typedef struct Private_Foo_ {
/* private elements */
} Private_Foo_;
static size_t Private_Foo_sizeof(void) { return sizeof(Private_Foo_); }
foo_private.h is written in a way, that it can be compiled into an object file. Use some helper program to link it and use the result of Private_Foo_sizeof() to generate the actual, plattform dependent foo.h from some foo.h.in file.
foo.h
#include
#define FOO_SIZEOF_PRIVATE_ELEMENTS <generated by preconfigure step>
typedef struct Foo_ {
/* public elements */
char reserved[FOO_SIZEOF_PRIVATE_ELEMENTS];
} Foo;
Foo *new_Foo(void);
void Foo_something_opaque(Foo* foo);
foo.c
#include "foo.h"
#include "foo_private.h"
Foo *new_Foo(void)
{
Foo *foo = malloc(sizeof(Foo));
/* initialize private and public elements */
return (Foo*) foo;
}
void Foo_something_opaque(Foo *foo)
{
Private_Foo_ *priv_foo = (Private_Foo_*) foo.reserved;
/* do something */
}
IMHO this is really messy. Now I'm a fan of smart containers (unfortunately there's no standard container library for C). Anyway: In such a container is creates through a function like
Array *array_alloc(size_t sizeofElement, unsigned int elements);
void *array_at(Array *array, unsigned int index);
/* and all the other functions expected of arrays */
See the libowfaw for an example of such an implementation. Now for the type Foo it was trivial to provide a function
Array *Foo_array(unsigned int count);
Object orientation is a way of thinking and modelling, data encapsulation where struct data should not be modified directly by the user can be implemented this way:
my_library.h
#ifndef __MY_LIBRARY__
#define __MY_LIBRARY__
typedef void MiObject;
MyObject* newMyObject();
void destroyMyObject(MyObject*)
int setMyObjectProperty1(MyObject*,someDataType1*);
/*Return a pointer to the data/object, classic pass by value */
someDataType1* getMyObjectProperty2Style1(MyObject*);
int setMyObjectProperty2(MyObject*,someDataType2*);
/* The data/object is passed through reference */
int getMyObjectProperty2Style2(MyObject*,someDataType2**);
/* Some more functions here */
#endif
my_library.c
struct _MyHiddenDataType{
int a;
char* b;
..
..
};
MyObject* newMyObject(){
struct _MyHiddenData* newData = (struct _MyHiddenData*)malloc(sizeof(struct _MyHiddenData);
//check null, etc
//initialize data, etc
return (MyObject*)newData;
}
int setMyObjectProperty1(MyObject* object,someDataType1* somedata){
struct _MyHiddenData* data = (struct _MyHiddenData*)object;
//check for nulls, and process somedata
data->somePropery=somedata;
}
someDataType1* getMyObjectProperty2Style1(MyObject*){
struct _MyHiddenData* data = (struct _MyHiddenData*)object;
//check for nulls, and process somedata
return data->someProperty;
}
/* Similar code for the rest */
And this way you have encapsulated the struct properties as if they were private. On the same manner static functions inside my_libray.c would behave as private functions. Get a good look at C and you'll see, that your imagination is the limit to what you can do.
I've been reading about OOP in C but I never liked how you can't have private data members like you can in C++. But then it came to my mind that you could create 2 structures. One is defined in the header file and the other is defined in the source file.
// =========================================
// in somestruct.h
typedef struct {
int _public_member;
} SomeStruct;
// =========================================
// in somestruct.c
#include "somestruct.h"
typedef struct {
int _public_member;
int _private_member;
} SomeStructSource;
SomeStruct *SomeStruct_Create()
{
SomeStructSource *p = (SomeStructSource *)malloc(sizeof(SomeStructSource));
p->_private_member = 42;
return (SomeStruct *)p;
}
From here you can just cast one structure to the other.
Is this considered bad practice? Or is it done often?
sizeof(SomeStruct) != sizeof(SomeStructSource). This will cause someone to find you and murder you someday.
Personally, I'd more like this:
typedef struct {
int _public_member;
/*I know you wont listen, but don't ever touch this member.*/
int _private_member;
} SomeStructSource;
It's C after all, if people want to screw up, they should be allowed to - no need to hide stuff, except:
If what you need is to keep the ABI/API compatible, there's 2 approaches that's more common from what I've seen.
Don't give your clients access to the struct, give them an opaque handle (a void* with a pretty name), provide init/destroy and accessor functions for everything. This makes sure you can change
the structure without even recompiling the clients if you're writing a library.
provide an opaque handle as part of your struct, which you can allocate however you like. This approach is even used in C++ to provide ABI compatibility.
e.g
struct SomeStruct {
int member;
void* internals; //allocate this to your private struct
};
You almost have it, but haven't gone far enough.
In the header:
struct SomeStruct;
typedef struct SomeStruct *SomeThing;
SomeThing create_some_thing();
destroy_some_thing(SomeThing thing);
int get_public_member_some_thing(SomeThing thing);
void set_public_member_some_thing(SomeThing thing, int value);
In the .c:
struct SomeStruct {
int public_member;
int private_member;
};
SomeThing create_some_thing()
{
SomeThing thing = malloc(sizeof(*thing));
thing->public_member = 0;
thing->private_member = 0;
return thing;
}
... etc ...
The point is, here now consumers have no knowledge of the internals of SomeStruct, and you can change it with impunity, adding and removing members at will, even without consumers needing to recompile. They also can't "accidentally" munge members directly, or allocate SomeStruct on the stack. This of course can also be viewed as a disadvantage.
I do not recommend using the public struct pattern. The correct design pattern, for OOP in C, is to provide functions to access every data, never allowing public access to data. The class data should be declared at the source, in order to be private, and be referenced in a forward manner, where Create and Destroy does allocation and free of the data. In a such way the public/private dilemma won't exist any more.
/*********** header.h ***********/
typedef struct sModuleData module_t'
module_t *Module_Create();
void Module_Destroy(module_t *);
/* Only getters and Setters to access data */
void Module_SetSomething(module_t *);
void Module_GetSomething(module_t *);
/*********** source.c ***********/
struct sModuleData {
/* private data */
};
module_t *Module_Create()
{
module_t *inst = (module_t *)malloc(sizeof(struct sModuleData));
/* ... */
return inst;
}
void Module_Destroy(module_t *inst)
{
/* ... */
free(inst);
}
/* Other functions implementation */
In the other side, if you do not want to use Malloc/Free (which can be unnecessary overhead for some situations) I suggest you hide the struct in a private file. Private members will be accessible, but that on user's stake.
/*********** privateTypes.h ***********/
/* All private, non forward, datatypes goes here */
struct sModuleData {
/* private data */
};
/*********** header.h ***********/
#include "privateTypes.h"
typedef struct sModuleData module_t;
void Module_Init(module_t *);
void Module_Deinit(module_t *);
/* Only getters and Setters to access data */
void Module_SetSomething(module_t *);
void Module_GetSomething(module_t *);
/*********** source.c ***********/
void Module_Init(module_t *inst)
{
/* perform initialization on the instance */
}
void Module_Deinit(module_t *inst)
{
/* perform deinitialization on the instance */
}
/*********** main.c ***********/
int main()
{
module_t mod_instance;
module_Init(&mod_instance);
/* and so on */
}
Never do that. If your API supports anything that takes SomeStruct as a parameter (which I'm expecting it does) then they could allocate one on a stack and pass it in. You'd get major errors trying to access the private member since the one the compiler allocates for the client class doesn't contain space for it.
The classic way to hide members in a struct is to make it a void*. It's basically a handle/cookie that only your implementation files know about. Pretty much every C library does this for private data.
Something similar to the method you've proposed is indeed used sometimes (eg. see the different varities of struct sockaddr* in the BSD sockets API), but it's almost impossible to use without violating C99's strict aliasing rules.
You can, however, do it safely:
somestruct.h:
struct SomeStructPrivate; /* Opaque type */
typedef struct {
int _public_member;
struct SomeStructPrivate *private;
} SomeStruct;
somestruct.c:
#include "somestruct.h"
struct SomeStructPrivate {
int _member;
};
SomeStruct *SomeStruct_Create()
{
SomeStruct *p = malloc(sizeof *p);
p->private = malloc(sizeof *p->private);
p->private->_member = 0xWHATEVER;
return p;
}
I'd write a hidden structure, and reference it using a pointer in the public structure. For example, your .h could have:
typedef struct {
int a, b;
void *private;
} public_t;
And your .c:
typedef struct {
int c, d;
} private_t;
It obviously doesn't protect against pointer arithmetic, and adds a bit of overhead for allocation/deallocation, but I guess it's beyond the scope of the question.
There are better ways to do this, like using a void * pointer to a private structure in the public struct. The way you are doing it you're fooling the compiler.
Use the following workaround:
#include <stdio.h>
#define C_PRIVATE(T) struct T##private {
#define C_PRIVATE_END } private;
#define C_PRIV(x) ((x).private)
#define C_PRIV_REF(x) (&(x)->private)
struct T {
int a;
C_PRIVATE(T)
int x;
C_PRIVATE_END
};
int main()
{
struct T t;
struct T *tref = &t;
t.a = 1;
C_PRIV(t).x = 2;
printf("t.a = %d\nt.x = %d\n", t.a, C_PRIV(t).x);
tref->a = 3;
C_PRIV_REF(tref)->x = 4;
printf("tref->a = %d\ntref->x = %d\n", tref->a, C_PRIV_REF(tref)->x);
return 0;
}
Result is:
t.a = 1
t.x = 2
tref->a = 3
tref->x = 4
I found that bit-field might be a good solution if you really want to hide something.
struct person {
unsigned long :64;
char *name;
int age;
};
struct wallet {
char *currency;
double balance;
};
The first member of struct person is an unnamed bit-field. used for a 64-bit pointer in this case. It's completely hidden and cannot be accessed by struct variable name.
Because of the first 64-bit in this struct is unused, so we can use it as a private pointer. We can access this member by its memory address instead of variable name.
void init_person(struct person* p, struct wallet* w) {
*(unsigned long *)p = (unsigned long)w;
// now the first 64-bit of person is a pointer of wallet
}
struct wallet* get_wallet(struct person* p) {
return (struct wallet*)*(unsigned long *)p;
}
A small working example, tested on my intel mac:
//
// Created by Rieon Ke on 2020/7/6.
//
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#if __x86_64__ || __LP64__
#define PRIVATE_SET(obj, val) *(unsigned long *) obj = (unsigned long) val;
#define PRIVATE_GET(obj, type) (type)*(unsigned long *) obj;
#define PRIVATE_POINTER unsigned long:64
#else
#define PRIVATE_SET(obj, val) *(unsigned int *) obj = (unsigned int) val;
#define PRIVATE_GET(obj, type) (type)*(unsigned int *) obj;
#define PRIVATE_POINTER unsigned int:32
#endif
struct person {
PRIVATE_POINTER;
char *name;
int age;
};
struct wallet {
char *currency;
double balance;
};
int main() {
struct wallet w;
w.currency = strdup("$$");
w.balance = 99.9;
struct person p;
PRIVATE_SET(&p, &w) //set private member
p.name = strdup("JOHN");
p.age = 18;
struct wallet *pw = PRIVATE_GET(&p, struct wallet*) //get private member
assert(strcmp(pw->currency, "$$") == 0);
assert(pw->balance == 99.9);
free(w.currency);
free(p.name);
return 0;
}
This approach is valid, useful, standard C.
A slightly different approach, used by sockets API, which was defined by BSD Unix, is the style used for struct sockaddr.
My solution would be to provide only the prototype of the internal struct and then declare the definition in the .c file. Very useful to show C interface and use C++ behind.
.h :
struct internal;
struct foo {
int public_field;
struct internal *_internal;
};
.c :
struct internal {
int private_field; // could be a C++ class
};
Note: In that case, the variable have to be a pointer because the compiler is unable to know the size of the internal struct.
Not very private, given that the calling code can cast back to a (SomeStructSource *). Also, what happens when you want to add another public member? You'll have to break binary compatibility.
EDIT: I missed that it was in a .c file, but there really is nothing stopping a client from copying it out, or possibly even #includeing the .c file directly.
Related, though not exactly hiding.
Is to conditionally deprecate members.
Note that this works for GCC/Clang, but MSVC and other compilers can deprecate too,
so its possible to come up with a more portable version.
If you build with fairly strict warnings, or warnings as errors, this at least avoids accidental use.
// =========================================
// in somestruct.h
#ifdef _IS_SOMESTRUCT_C
# if defined(__GNUC__)
# define HIDE_MEMBER __attribute__((deprecated))
# else
# define HIDE_MEMBER /* no hiding! */
# endif
#else
# define HIDE_MEMBER
#endif
typedef struct {
int _public_member;
int _private_member HIDE_MEMBER;
} SomeStruct;
#undef HIDE_MEMBER
// =========================================
// in somestruct.c
#define _IS_SOMESTRUCT_C
#include "somestruct.h"
SomeStruct *SomeStruct_Create()
{
SomeStructSource *p = (SomeStructSource *)malloc(sizeof(SomeStructSource));
p->_private_member = 42;
return (SomeStruct *)p;
}
An anonymous struct can be of use here.
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct {
int i;
struct {
int j;
} MYSTRUCT_PRIVATE;
// NOTE: Avoid putting public members after private
int k;
} MyStruct;
void test_mystruct();
#endif
In any file that should have access to the private members, define MYSTRUCT_PRIVATE as an empty token before including this header. In those files, the private members are in an anonymous struct and can be accessed using m.j, but in all other places they can only be accessed using m.MYSTRUCT_PRIVATE.j.
#define MYSTRUCT_PRIVATE
#include "mystruct.h"
void test_mystruct() {
// Can access .j without MYSTRUCT_PRIVATE in both
// initializer and dot operator.
MyStruct m = { .i = 10, .j = 20, .k = 30 };
m.j = 20;
}
#include <stdio.h>
#include "mystruct.h"
int main() {
// You can declare structs and, if you jump through
// a small hoop, access private members
MyStruct m = { .i = 10, .k = 30 };
m.MYSTRUCT_PRIVATE.j = 20;
// This will not work
//MyStruct m2 = { .i = 10, .j = 20, .k = 30 };
// But this WILL work, be careful
MyStruct m3 = { 10, 20, 30 };
test_mystruct();
return 0;
}
I do not recommend putting public members after private members. Initializing a struct without member designators, such as with { 10, 20, 30 } can still initialize private members. If the number of private members changes, this will also silently break all initializers without member designators. It's probably best to always use member designators to avoid this.
You must design your structs, and especially the private members, to be zero initialized since there are no automatic constructors as in C++. As long as the members are initialized to 0 then they won't be left in an invalid state even without an initialization function. Barring a member designator initialization, initializing to simply { 0 } should be designed to be safe.
The only downside I've found is that this does mess with things like debuggers and code completion, they typically don't like it when one type has one set of members in one file, and a different set in another file.
Here's a very organized way to do it using macros. This is how I've seen it used in some of the big projects. I will assume the following:
Header file with the struct
Source file with access to private fields
Source file with no access to private fields (the fields exist but are renamed).
Header file:
// You can put this part in a header file
// and share it between multiple header files in your project
#ifndef ALLOW_PRIVATE_ACCESS
#define PRIVATE(T) private_##T
#else
#define PRIVATE(T) T
#endif
#define PUBLIC(T) T
typedef struct {
int PRIVATE(m1); // private member
int PUBLIC(m2); // public member
} mystruct;
mystruct *mystruct_create(void);
int mystruct_get_m1(mystruct *t);
Source file with access to private fields:
#include <stdlib.h>
#define ALLOW_PRIVATE_ACCESS
#include "mystruct.h"
mystruct *mystruct_create(void) {
mystruct *p = (mystruct *)malloc(sizeof(mystruct));
p->m1 = 42; // works (private)
p->m2 = 34; // works (public)
return (mystruct *)p;
}
int mystruct_get_m1(mystruct *t) {
return t->m1; // works (private)
}
Source file with no access to private fields:
#include <stdio.h>
#include <stdlib.h>
#include "mystruct.h"
int main() {
mystruct *t = mystruct_create();
printf("t->m1 = %d\n", t->m1); // error (private)
printf("t->m1 = %d\n", mystruct_get_m1(t)); // works (using function)
printf("t->m2 = %d\n", t->m2); // works (public)
free(t);
return 0;
}