I was experimenting with C11 and VLAs, trying to declare a struct variable on the stack with only an incomplete declaration. The objective is to provide a mechanism to create a variable of some struct type without showing the internals (like the PIMPL idiom) but without the need to create the variable on the heap and return a pointer to it. Also, if the struct layout changes, I don't want to recompile every file that uses the struct.
I have managed to program the following:
private.h:
#ifndef PRIVATE_H_
#define PRIVATE_H_
typedef struct A{
int value;
}A;
#endif /* PRIVATE_H_ */
public.h:
#ifndef PUBLIC_H_
#define PUBLIC_H_
typedef struct A A;
size_t A_getSizeOf(void);
void A_setValue(A * a, int value);
void A_printValue(A * a);
#endif /* PUBLIC_H_ */
implementation.c:
#include "private.h"
#include "stdio.h"
size_t A_getSizeOf(void)
{
return sizeof(A);
}
void A_setValue(A * a, int value)
{
a->value = value;
}
void A_printValue(A * a)
{
printf("%d\n", a->value);
}
main.c:
#include <stdalign.h>
#include <stddef.h>
#include "public.h"
#define createOnStack(type, variable) \
alignas(max_align_t) char variable ## _stack[type ## _getSizeOf()]; \
type * variable = (type *)&variable ## _stack
int main(int argc, char *argv[]) {
createOnStack(A, var);
A_setValue(var, 5335);
A_printValue(var);
}
I have tested this code and it seems to work. However I'm not sure if I'm overlooking something (like aliasing, alignment or something like that) that could be dangerous or unportable, or could hurt performance. Also I want to know if there are better (portable) solutions to this problem in C.
This of course violates the effective typing rules (aka strict aliasing) because the C language does not allow an object of tye char [] to be accessed through a pointer that does not have that type (or a compatible one).
You could disable strict aliasing analysis via compiler flags like -fno-strict-aliasing or attributes like
#ifdef __GNUC__
#define MAY_ALIAS __attribute__((__may_alias__))
#else
#define MAY_ALIAS
#endif
(thanks go to R.. for pointing out the latter), but even if you do not do so, in practice everything should work just fine as long as you only ever use the variable's proper name to initialize the typed pointer.
Personally, I'd simplify your declarations to something along the lines of
#define stackbuffer(NAME, SIZE) \
_Alignas (max_align_t) char NAME[SIZE]
typedef struct Foo Foo;
extern const size_t SIZEOF_FOO;
stackbuffer(buffer, SIZEOF_FOO);
Foo *foo = (void *)buffer;
The alternative would be using the non-standard alloca(), but that 'function' comes with its own set of issues.
I am considering adopting a strategy similar to the following to solve essentially the same problem. Perhaps it will be of interest despite being a year late.
I wish to prevent clients of a struct from accessing the fields directly, in order to make it easier to reason about their state and easier to write reliable design contracts. I'd also prefer to avoid allocating small structures on the heap. But I can't afford a C11 public interface - much of the joy of C is that almost any code knows how to talk to C89.
To that end, consider the adequate application code:
#include "opaque.h"
int main(void)
{
opaque on_the_stack = create_opaque(42,3.14); // constructor
print_opaque(&on_the_stack);
delete_opaque(&on_the_stack); // destructor
return 0;
}
The opaque header is fairly nasty, but not completely absurd. Providing both create and delete functions is mostly for the sake of consistency with structs where calling the destructor actually matters.
/* opaque.h */
#ifndef OPAQUE_H
#define OPAQUE_H
/* max_align_t is not reliably available in stddef, esp. in c89 */
typedef union
{
int foo;
long long _longlong;
unsigned long long _ulonglong;
double _double;
void * _voidptr;
void (*_voidfuncptr)(void);
/* I believe the above types are sufficient */
} alignment_hack;
#define sizeof_opaque 16 /* Tedious to keep up to date */
typedef struct
{
union
{
char state [sizeof_opaque];
alignment_hack hack;
} private;
} opaque;
#undef sizeof_opaque /* minimise the scope of the macro */
void print_opaque(opaque * o);
opaque create_opaque(int foo, double bar);
void delete_opaque(opaque *);
#endif
Finally an implementation, which is welcome to use C11 as it's not the interface. _Static_assert(alignof...) is particularly reassuring. Several layers of static functions are used to indicate the obvious refinement of generating the wrap/unwrap layers. Pretty much the entire mess is amenable to code gen.
#include "opaque.h"
#include <stdalign.h>
#include <stdio.h>
typedef struct
{
int foo;
double bar;
} opaque_impl;
/* Zero tolerance approach to letting the sizes drift */
_Static_assert(sizeof (opaque) == sizeof (opaque_impl), "Opaque size incorrect");
_Static_assert(alignof (opaque) == alignof (opaque_impl), "Opaque alignment incorrect");
static void print_opaque_impl(opaque_impl *o)
{
printf("Foo = %d and Bar = %g\n",o->foo,o->bar);
}
static void create_opaque_impl(opaque_impl * o, int foo, double bar)
{
o->foo = foo;
o->bar = bar;
}
static void create_opaque_hack(opaque * o, int foo, double bar)
{
opaque_impl * ptr = (opaque_impl*)o;
create_opaque_impl(ptr,foo,bar);
}
static void delete_opaque_impl(opaque_impl *o)
{
o->foo = 0;
o->bar = 0;
}
static void delete_opaque_hack(opaque * o)
{
opaque_impl * ptr = (opaque_impl*)o;
delete_opaque_impl(ptr);
}
void print_opaque(opaque * o)
{
return print_opaque_impl((opaque_impl*)o);
}
opaque create_opaque(int foo, double bar)
{
opaque tmp;
unsigned int i;
/* Useful to zero out padding */
for (i=0; i < sizeof (opaque_impl); i++)
{
tmp.private.state[i] = 0;
}
create_opaque_hack(&tmp,foo,bar);
return tmp;
}
void delete_opaque(opaque *o)
{
delete_opaque_hack(o);
}
The drawbacks I can see myself:
Changing the size define manually would be irritating
The casting should hinder optimisation (I haven't checked this yet)
This may violate strict pointer aliasing. Need to re-read the spec.
I am concerned about accidentally invoking undefined behaviour. I would also be interested in general feedback on the above, or whether it looks like a credible alternative to the inventive VLA technique in the question.
Related
I have the following in C (not C++!):
module.c
struct Private {...};
void foo(void* private, int param) {...}
module.h
#define PRIVATE_SIZE ???;
void foo(void* private, int param);
main.c
char m1[PRIVATE_SIZE];
char m2[PRIVATE_SIZE];
int main()
{
foo(m1, 10);
foo(m2, 20);
}
How can I expose sizeof(Private) at compile time so that application can statically allocate its storage without exposing Private type?
Note, this is a very limited embedded system and dynamic allocation is not available.
You shouldn't expose the size of the struct to the caller, because that breaks the whole purpose of having private encapsulation in the first place. Allocation of your private data is no business of the caller. Also, avoid using void* because they complete lack type safety.
This is how you write private encapsulation in C:
In module.h, forward declare an incomplete type typedef struct module module;.
In module.c, place the struct definition of this struct. it will only be visible to module.c and not to the caller. This is known as opaque types.
The caller can only allocate pointers to this struct, never allocate objects.
Caller code might look like:
#include "module.h"
...
module* m;
result = module_init(&m)
And the module_init function acts as a "constructor", declared in module.h and defined in module.c:
bool module_init (module** obj)
{
module* m = malloc(sizeof *m);
...
m->something = ...; // init private variables if applicable
*obj = m;
return true;
}
If the caller does need to know the size of the objects, it would only be for the purpose of hard copy etc. If there's a need for that, provide a copy function which encapsulates the allocation and copy ("copy constructor"), for example:
result module_copy (module** dst, const module* src);
Edit:
Please note that the manner of allocation is a separate issue. You don't have to use dynamic allocation for the above design. In embedded systems for example, it is common to use static memory pools instead. See Static allocation of opaque data types
You can't allocate size for a struct such as this because it isn't known at compile time. Even if you did know the size at run time, you'd still have issues due to alignment.
There is a possible solution which involves defining a separate structure that has the same size and alignment requirements as the private struct.
For example:
module.h:
#include <inttypes.h>
struct Public {
uint64_t opaque1;
uint64_t opaque2;
uint64_t opaque3;
};
void init(struct Public *p);
module.c:
#include <assert.h>
#include <stdalign.h>
#include "module.h"
struct Private {
int a;
double b;
float c;
};
static_assert(sizeof(struct Private)==sizeof(struct Public), "sizes differ");
static_assert(alignof(struct Private)==alignof(struct Public), "alignments differ");
void init(struct Public *p)
{
struct Private *pr = (struct Private *)p;
pr->a = 2;
pr->b = 2.5;
pr->c = 2.4f;
}
The Public and Private structs are guaranteed to have the same size, and the alignment should be the same. There is the possibility of the user writing the the "opaque" fields of the public struct, in which case you could have aliasing issues regarding effective types, but if the user can be trusted to do that then this should work.
Another, more robust option, is if you have some idea of the maximum number of objects you want to support. If that's the case, you can have a static array of these objects in your implementation file, and the init function would return a pointer to one of the objects in this list. Then you'd have a related cleanup function that would free the instance.
For example:
module.c:
struct Private {
int a;
double b;
float c;
};
struct PrivateAllocator {
struct Private obj;
int used;
};
struct PrivateAllocator list[5] = {
{ { 0, 0, 0}, 0 },
{ { 0, 0, 0}, 0 },
{ { 0, 0, 0}, 0 },
{ { 0, 0, 0}, 0 },
{ { 0, 0, 0}, 0 }
};
struct Private *private_init()
{
int i;
for (i=0; i<5; i++) {
if (!list[i].used) {
list[i].used = 1;
return &list[i].obj;
}
}
return NULL;
}
void private_free(struct Private *p)
{
int i;
for (i=0; i<5; i++) {
if (&list[i].obj == p) {
list[i].used = 0;
return;
}
}
}
In conforming C code you can't create a static instance of an arbitrary unknown type even if you know its size at compile time (not even if you know the alignment).
Let's say you try doing it anyway. How would you do it, given the size in a macro or enum PRIVATE_SIZE?
unsigned char obj[PRIVATE_SIZE];
And then you'd pass (void*)obj to wherever its needed, right?
Well, this breaks the aliasing rules. While you can legally access any individual char/byte in any object, you can't do it the other way around saying that those chars are not chars, they are just storage behind other types. That is, you can't legally have a short int superimposed on top of, say, obj[2] and obj[3] through smarty-pants casts (e.g. ((struct Private*)obj)->my_short = 2;). The only legal way to do something like this would be through memcpy(), e.g. memcpy(&temp, obj, sizeof temp); and then back after the modification. Or you'd need to work with individual chars of obj[].
There are two possible ways to sort of do it. One is described in another answer, basically define the instance where the type is known, but only let the outside world have a pointer to it.
Another, very similar, define it in assembly code and, again, let the outside world have a pointer to it. The "beauty" of the assembly way is that you really only need a name, an alignment and a size to allocate space for a named object.
And if you put the instances into a special data section (see the gcc's section attribute and the linker scripts), you may even have all of the instances in the same place (think, array) and even find out their cumulative size and therefore count.
Yet another thing to do while not explicitly violating any C rules is to still use this unsigned char obj[PRIVATE_SIZE] trick, but launder it by passing it unchanged through an assembly function that the C compiler can't look into, e.g. something like
// struct Private* launder(unsigned char*);
.text
.globl launder
launder:
move %first_param_reg, %return_reg
ret
But you'll really need to change unsigned char obj[PRIVATE_SIZE] to something that would have proper alignment on your architecture, e.g. double obj[PRIVATE_SIZE / sizeof(double)] (or the same with long long if you like that way better).
As for PRIVATE_SIZE, you can have a check at compile time that it matches the size of the type, e.g.
#include "mod.h" // mod.h defines PRIVATE_SIZE
struct Private { ... };
extern char StAtIcAsSeRt[sizeof(struct Private) == PRIVATE_SIZE];
How to expose C struct size without exposing its type?
If able to compromise a bit: (statically --> main() local)
with variable length arrays (C99), use a helper function and put the array in main().
module.h
size_t foo_size(void);
main.c
int main() {
char m1[foo_size()];
foo(m1, 10);
}
Additional work needed to account for alignment issues.
Consider relaxing your goal as suggested.
C99 allowes you to use variable length array.
private.h:
#include <stdio.h>
extern const size_t size;
private.c:
#include "private.h"
struct Private {
int x;
int y;
int z;
};
const size_t size = sizeof(struct Private);
main.c:
#include <stdio.h>
#include "private.h"
int main(void) {
char m1[size]; //variable length array
printf("Size of m1 = %ld\n", sizeof(m1));
}
There are a lot of questions out there about forward declarations and opaque types, but most seem to be from the perspective of the library author, or people trying to use incomplete types without pointers or some such.
I'm using a library whose interface accepts/returns FOO * pointers. I'd like to confirm that I cannot (or should not) somehow forward-declare FOO or FOO * in my header file (which defines a struct with a FOO * member).
I do know that I could just #include <library.h> in both my header and my .c file, but since this is really just a learning project, I wanted to get clarification. (On the one hand, it seems like a forward-declaration might be possible, since my struct member is only a pointer and thus its size is known without knowing what FOO is—but on the other hand, I don't know if it's valid/smart to typedef something to FOO when the library is already doing that.)
Thanks in advance!
Assuming you never need to dereference the pointer, then you can use an opaque type pointer if you know the struct tag name for it:
typedef struct FOO FOO;
You can now create FOO * variables, and use them. And you probably could find the structure tag from the header file, but you should be aware that the library owners could change it at any time.
It is still usually best to include the official header, but if most of your code is not accessing the actual library, just passing around a handle to something returned by the library, you can avoid the 'cost' of including the actual header. You should measure what that cost is before deciding on what is probably premature optimization. It might be argued that if you have to ask the question, you don't know enough to be sure of doing it right, and you're in danger of getting burnt.
Note that you cannot create actual variables of the type; for that to work, the compiler needs to know how big the structure actually is, which means you need the details from the header.
Strictly speaking, if you don't know the tag name, that won't work. And likewise, if the structure doesn't have a tag, you can't do it either. And if it isn't a structure type, you can't do it.
Note that if you know the structure tag, you can also write:
struct FOO *fp;
If you have to get inventive, everything works for passing around pointers until you reach the point where you need to access the actual library functions. Then you need the actual library header (to make sure the information is right), and if your structure tag is wrong, all hell breaks loose. So, if you're going to play this game, make sure you get the structure tag correct.
Note that C11 allows a typedef to be repeated as long as it is the same each time, whereas earlier versions of C did not allow that. This can be a considerable help.
Working example
This is close to a minimal example that shows how it might be done. It assumes C11 where the repeated typedef is legitimate. It won't work for C99 or C89/C90 because the typedef for FOO is repeated when projfunc.c is compiled. (There are various ways you can adapt it so that it will work in C99 or earlier, but they're messier, using #ifdef or similar around the project.h typedef — since the presumption is that you can't alter library.h; if you can, it is part of your project after all.)
The project.h header is used primarily by the general code that belongs to the project that uses the library defining FOO — which is represented by projmain.c in this example. It can be used on its own, or with library.h, which is illustrated by projfunc.c which is the project code that actually interfaces to the library and makes calls to the library. The file library.c only uses library.h.
You can play with alternative declarations of FOO in project.h to see what goes wrong where. For example, typedef struct BAR FOO; will fail; so will typedef struct FOO *FOO;.
project.h
#ifndef PROJECT_H_INCLUDED
#define PROJECT_H_INCLUDED
typedef struct FOO FOO;
typedef struct Project
{
FOO *foop;
char *name;
int max;
double ratio;
} Project;
extern int proj_function(Project *pj);
#endif /* PROJECT_H_INCLUDED */
library.h
#ifndef LIBRARY_H_INCLUDED
#define LIBRARY_H_INCLUDED
typedef struct FOO
{
int x;
int y;
} FOO;
extern FOO *foo_open(const char *file);
extern int foo_close(FOO *foop);
extern int foo_read(FOO *foop, int *x, int *y);
extern int foo_write(FOO *foop, int x, int y);
#endif /* LIBRARY_H_INCLUDED */
projmain.c
#include "project.h"
int main(void)
{
Project pj = { 0, 0, 0, 0.0 };
if (proj_function(&pj) != 0)
return 1;
return 0;
}
projfunc.c
#include "project.h"
#include "library.h"
#include <stdio.h>
int proj_function(Project *pj)
{
int x, y;
pj->foop = foo_open("classic-mode");
if (foo_write(pj->foop, 1, 2) < 0)
{
foo_close(pj->foop);
return -1;
}
if (foo_read(pj->foop, &x, &y) < 0)
{
foo_close(pj->foop);
return -1;
}
printf("x = %d, y = %d\n", x, y);
return 0;
}
library.c
#include "library.h"
#include <assert.h>
static FOO foo = { 0, 0 };
FOO *foo_open(const char *file)
{
assert(file != 0);
return &foo;
}
int foo_close(FOO *foop)
{
assert(foop == &foo);
foo.x = foo.y = 0;
return 0;
}
int foo_read(FOO *foop, int *x, int *y)
{
assert(foop == &foo);
*x = foop->x + 1;
*y = foo.y + 1;
return 0;
}
int foo_write(FOO *foop, int x, int y)
{
assert(foop == &foo);
foo.x = x + 1;
foop->y = y + 2;
return 0;
}
The library should define FOO for you, either opaquely or transparently, as it's own source refers to FOO.
#include <library.h> should get you the prototypes to the functions the library provides, and also the types needed to interact with them.
If you create your own FOO type, you'll almost certainly get a compile error indicating multiple definition of 'FOO' when you include the function prototypes from the library.
Having the following piece of code:
File: types.h
typedef struct Struct_A_T
{
int A;
char B;
float C;
}Struct_A;
File: code.c
#include "types.h"
void Function(const void *const ptr)
{
Struct_A localStruct = *((Struct_A *)ptr);
localStruct.A = 1000;
localStruct.B = 250;
localStruct.C = 128.485;
}
File: main.c
#include "types.h"
void Function(const void *const ptr);
int main(void)
{
Struct_A MyStruct1 = {2, 5, 2.8};
float local = 24.785;
/* Correct call */
Function(&MyStruct1);
/* Incorrect call!!! */
Function(&local);
}
And knowing that a pointer to void can be used as a "generic" pointer. How can I detect inside "Function" that the type passed in the void pointer is the correct in order to avoid the run time error provoked by the last call in the file main.c?
There's no way to do it using language features. It can only be done manually.
I, for one, use the following technique in debug builds of the code
typedef struct Struct_A_T
{
int A;
char B;
float C;
#ifdef DEBUG
unsigned signature;
#endif /* DEBUG */
}Struct_A;
i.e. in debug configuration I introduce an additional field into the structure. Each object of that struct type has to have that field initialized with some pre-determined "unpredictable" signature value specific for this type, like
#define STRUCT_A_SIGNATURE 0x12345678
which is easy to do if all structures are created in some centralized fashion (like allocated dynamically or initialized by a dedicated function). This might be more cumbersome if there's no such centralized location. But that the price we sometimes have to pay for safety. For example, in your example case that would be
Struct_A MyStruct1 = {2, 5, 2.8, 0x12345678 };
BTW, designated initializers might make such initializations more stable and it easier to read.
And then, in order to convert pointers from void * to the specific type I use the following cast macro
#ifdef DEBUG
#define TO_STRUCT_A(p)\
(assert((p) == NULL || ((Struct_A *)(p))->signature == STRUCT_A_SIGNATURE),\
(Struct_A *)(p))
#else /* DEBUG */
#define TO_STRUCT_A(p) ((Struct_A *)(p))
#endif /* DEBUG */
meaning that inside your Function you'd do
Struct_A localStruct = *TO_STRUCT_A(ptr);
which with very high probability will trigger assertion failure if a pointer to wrong type is passed to Function.
This all can (and should) be implemented using a more generic set of macros, of course.
Obviously, this only works for struct types, into which you can inject that additional signature field. Another potential problem with this approach is that by introducing an extra field into the structure in debug builds one can potentially cause the behavior of debug and release build to diverge.
You can't, that's the primary downside of void*, you have no way to determine what is being pointed to. You just have to know.
You may use sizeof to compare sizes of the struct to that which void* points points to. This is not a sufficient but necessary condition that a pointer to your struct type is passed to Function. BTW the property of languages with the possibility to check metadata (incl. types) of variables and wider is called reflection. It is available in many modern languages and some bits have been included recently in C++11, but C still lacks it.
I don't even know, whether what I'm asking is something stupid or not. I am not asking you to write any code for me, but an idea to do something in a better way.
I have a struct with a large number of items like this:
typedef struct _myStruct
{
int int1;
char char1;
int int2;
:
:
int int50;
}myStruct;
I have another enumeration which has a single entry for each item in myStruct.
enum
{
eINT1,
eCHAR1,
eINT2,
:
:
eINT50
} PARAMETER_ID;
I want to write a function for each data type [say one for int, one for char, one for string etc], which return the value of a member of myStruct, when the PARAMETER_ID is given as input.
For example I need a int GetInt(PARAMETER_ID) function which return the value of int1 when eINT1 is passed as an argument. Similarly I am going to have char GetCharacter(PARAMETER_ID), float GetFloat(PARAMETER_ID) etc.
The number of items in the struct can be large. So using a switch-case for each item will not be a viable option.
Only other option I can think of is using the address of the structure variable and offsetof() function to calculate the address of the parameter and then by memcpying the required bytes into a variable. In that case I need to keep the offset of each parameter somewhere, but that is not a problem.
I am looking for alternate options to do this. Any help will be greatly appreciated.
Thank you.
A large switch is a good viable option.
You might also play preprocessor tricks.
You could have a mystruct.def file containing
INTFIELD(int1)
CHARFIELD(char1)
INTFIELD(int2)
etc... Then you would include it several times; to declare the structure:
struct _myStruct {
#define INTFIELD(F) int F;
#define CHARFIELD(F) char F;
#include "mystruct.def"
#undef INTFIELD
#undef CHARFIELD
};
To declare the enumeration (using e_int1 instead of eINT1)
enum field_en {
#define INTFIELD(F) e_##F,
#define CHARFIELD(F) e_##F,
#include "mystruct.def"
#undef INTFIELD
#undef CHARFIELD
};
To implement the accessor,
int get_int(struct _myStruct*s, enum field_en f)
{
switch (f) {
#define INTFIELD(F) case e_##F: return s->F;
#define CHARFIELD(F) /*nothing*/
#include "mystruct.def"
#undef INTFIELD
#undef CHARFIELD
default: return 0;
}}
I don't claim this is better or more readable code, but that kind of programming style does appear in some C or C++ programs (e.g. GCC internals with its gcc/tree.def)
If you code is a very large code base, and you are ready to spend days of work (e.g. because you have a lot of such struct and don't want to play such tricks) you might consider making a GCC extension with MELT (a high-level domain specific language to extend GCC) to help you; you probably can make a MELT extension to generate the accessor functions for you.
You could also convince your boss to generate both the struct, the enum and the accessor functions from an ad-hoc descriptive file (using awk, python or whatever). GCC does such tricks for its options file, e.g. gcc/common.opt
At last, if the header containing the _myStruct is so sacred that you are not allowed to touch it, and if it is very cleanly formatted, you might make an ad-hoc (e.g. awk) script to get that declaration and process it.
NB a good compiler optimizes dense switch statements as indexed jumps which take constant time, even for hundred of cases.
#include <stddef.h>
#include <stdio.h>
struct S
{
int int1;
char char1;
int int2;
char char2;
long long1;
} myStruct = {12345, 'A', 321, 'B', -1L};
enum
{
eINT1 = offsetof(struct S, int1),
eCHAR1 = offsetof(struct S, char1),
eINT2 = offsetof(struct S, int2),
eCHAR2 = offsetof(struct S, char2),
eLONG1 = offsetof(struct S, long1),
} PARAMETER_ID;
char GetChar(int para_id)
{
return *((char*)((char *)&myStruct + para_id));
}
int GetInt(int para_id)
{
return *((int*)((char *)&myStruct + para_id));
}
long GetLong(int para_id)
{
return *((long*)((char *)&myStruct + para_id));
}
void main(void)
{
printf("offsetof int1 = %d\n", eINT1);
printf("offsetof char1 = %d\n", eCHAR1);
printf("offsetof int2 = %d\n", eINT2);
printf("offsetof char2 = %d\n", eCHAR2);
printf("offsetof long1 = %d\n", eLONG1);
printf("int1 = %d\n", GetInt (eINT1));
printf("char1 = %c\n", GetChar(eCHAR1));
printf("int2 = %d\n", GetInt (eINT2));
printf("char2 = %c\n", GetChar(eCHAR2));
printf("long1 = %ld\n", GetLong(eLONG1));
}
You partially answer your own question, offsetof is meant to be used for this very purpose. You have to consider struct padding/alignment. I think you are looking for something similar to this:
#include <stddef.h> // size_t, offsetof
#include <string.h> // memcpy
#include <stdio.h>
typedef struct
{
int int1;
char char1;
int int2;
int int50;
} myStruct;
typedef enum
{
eINT1,
eCHAR1,
eINT2,
eINT50,
ITEMS_IN_STRUCT
} myEnum;
static const size_t MYSTRUCT_MEMBER_OFFSET [ITEMS_IN_STRUCT] =
{
offsetof(myStruct, int1),
offsetof(myStruct, char1),
offsetof(myStruct, int2),
offsetof(myStruct, int50),
};
static const myStruct MS;
static const size_t MYSTRUCT_MEMBER_SIZE [ITEMS_IN_STRUCT] =
{
sizeof(MS.int1),
sizeof(MS.char1),
sizeof(MS.int2),
sizeof(MS.int50)
};
void myStruct_get_member (void* result, const myStruct* ms, myEnum id)
{
memcpy (result,
(char*)ms + MYSTRUCT_MEMBER_OFFSET[id],
MYSTRUCT_MEMBER_SIZE[id]);
}
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;
}