I'm trying to correctly implement an opaque pointer (aka handle) for library users to interact with my library without knowing internal details.
The setup is roughly like so:
typedef MyAlign double; // largest data type
struct MyImplementation {
int a;
char b[3];
double c;
char d[5];
};
struct MyHandle {
char __private[sizeof(struct MyImplementation) - sizeof(MyAlign)];
MyAlign __align;
};
// Some static asserts about size and alignment...
My question is, how can I be sure the MyHandle has the same alignment when larger types are added to the original structure (eg another structure)? Ideally I'd want the build to fail whenever these sorts of assumption breaking changes are made.
One normally use pointers for opaque types.
foo.h:
// Incomplete struct as an opaque type.
// You could also use `typedef struct Foo *Foo;`
// (with the appropriate changes to the prototypes).
typedef struct Foo Foo;
Foo *Foo_new( ... );
void Foo_delete( Foo * );
void Foo_method1( Foo *, ... );
void Foo_method2( Foo *, ... );
...
foo.c:
#include "foo.h"
struct Foo {
...
};
Foo *Foo_new( ... ) { ... }
void Foo_delete( Foo *foo ) { ... }
void Foo_method1( Foo *foo, ... ) { ... }
void Foo_method2( Foo *foo, ... ) { ... }
...
Foo_new is aware of the implementation, and thus will always return a properly-aligned pointer.
Related
I've been trying to work out how legal the below is and I could really use some help.
#include <stdio.h>
#include <stdlib.h>
typedef struct foo {
int foo;
int bar;
} foo;
void make_foo(void * p)
{
foo * this = (foo *)p;
this->foo = 0;
this->bar = 1;
}
typedef struct more_foo {
int foo;
int bar;
int more;
} more_foo;
void make_more_foo(void * p)
{
make_foo(p);
more_foo * this = (more_foo *)p;
this->more = 2;
}
int main(void)
{
more_foo * mf = malloc(sizeof(more_foo));
make_more_foo(mf);
printf("%d %d %d\n", mf->foo, mf->bar, mf->more);
return 0;
}
As far as I've gathered, doing this is type punning and is supposed to violate the strict aliasing rule. Does it, though? The pointers passed around are void. You are allowed to interpret a void pointer any way you wish, correct?
Also, I read that there may be memory alignment issues. But struct alignment is deterministic. If the initial members are the same, then they'll get aligned the same way, and there should be no problems accessing all foo members from a more_foo pointer. Is that correct?
GCC compiles with -Wall without warnings, the program runs as expected. However, I'm not sure if it's UB or not and why.
I also saw that this:
typedef union baz {
struct foo f;
struct more_foo mf;
} baz;
void some_func(void)
{
baz b;
more_foo * mf = &b.mf; // or more_foo * mf = (more_foo *)&b;
make_more_foo(mf);
printf("%d %d %d\n", mf->foo, mf->bar, mf->more);
}
seems to be allowed. Because of the polymorphic nature of unions the compiler would be ok with it. Is that correct? Does that mean that by compiling with strict aliasing off you don't have to use an union and can use only structs instead?
Edit: union baz now compiles.
The authors of the Standard didn't think it necessary to specify any means by which an lvalue of a struct or union's member type may be used to access the underlying struct or union. The way N1570 6.5p7 is written doesn't even allow for someStruct.member = 4; unless member if of character type. Being able to apply the & operator to struct and union members wouldn't make any sense, however, unless the authors of the Standard expected that the resulting pointers would be useful for something. Given footnote 88: "The intent of this list is to specify those circumstances in which an object may or may not be aliased", the most logical expectation is that it was only intended to apply in cases where lvalues' useful lifetimes would overlap in ways that would involve aliasing.
Consider the two functions within the code below:
struct s1 {int x;};
struct s2 {int x;};
union {struct s1 v1; struct s2 v2;} arr[10];
void test1(int i, int j)
{
int result;
{ struct s1 *p1 = &arr[i].v1; result = p1->x; }
if (result)
{ struct s2 *p2 = &arr[j].v2; p2->x = 2; }
{ struct s1 *p3 = &arr[i].v1; result = p3->x; }
return result;
}
void test2(int i, int j)
{
int result;
struct s1 *p1 = &arr[i].v1; result = p1->x;
if (result)
{ struct s2 *p2 = &arr[j].v2; p2->x = 2; }
result = p1->x; }
return result;
}
In the test1, even if i==j, all pointer that will ever be accessed during p1's lifetime will be accessed through p1, so p1 won't alias anything. Likewise with p2 and p3. Thus, since there is no aliasing, there should be no problem if i==j. In test2, however, if i==j, then the creation of p1 and the last use of it to access p1->x would be separated by another action which access that storage with a pointer not derived from p1. Consequently, if i==j, then the access via p2 would alias p1, and per N1570 5.6p7 a compiler would not be required to allow for that possibility.
If the rules of 5.6p7 are applicable even in cases that don't involve actual aliasing, then structures and unions would be pretty useless. If they only apply in cases that do involve actual aliasing, then a lot of needless complexity like the "Effective Type" rules could be done away with. Unfortunately, some compilers like gcc and clang use the rules to justify "optimizing" the first function above and then assuming that they don't have to worry about the resulting alias which is present in their "optimized" version but wasn't in the original.
Your code will work fine in any compiler whose authors make any effort to recognize derived lvalues. Both gcc and clang, however, will botch even the test1() function above unless they are invoked with the -fno-strict-aliasing flag. Given that the Standard doesn't even allow for someStruct.member = 4;, I'd suggest that you refrain from the kind of aliasing seen in test2() above and not bother targeting compilers that can't even handle test1().
I'd say it isn't strict since if you change "foo" structure, "more foo" structure will have to change with it . "foo" must become the base of "more foo", this is inheritance, not quite polymorphism. But you can use function pointers to introduce polymorphism to help with these structures.
Example
#include <stdio.h>
#include <stdlib.h>
#define NEW(x) (x*)malloc(sizeof(x));
typedef struct
{
void(*printme)(void*);
int _foo;
int bar;
} foo;
typedef struct
{
// inherits foo
foo base;
int more;
} more_foo;
void foo_print(void *t)
{
foo *this = (foo*)t;
printf("[foo]\r\n\tfoo=%d\r\n\tbar=%d\r\n[/foo]\r\n", this->bar, this->_foo);
}
void more_foo_print(void *t)
{
more_foo *this = t;
printf("[more foo]\r\n");
foo_print(&this->base);
printf("\tmore=%d\r\n", this->more);
printf("[/more foo]\r\n");
}
void foo_construct( foo *this, int foo, int bar )
{
this->_foo = foo;
this->bar = bar;
this->printme = foo_print;
}
void more_foo_construct(more_foo *t, int _foo, int bar, int more)
{
foo_construct((foo*)t, _foo, bar);
t->more = more;
// Overrides printme
t->base.printme = more_foo_print;
}
more_foo *new_more_foo(int _foo, int bar, int more)
{
more_foo * new_mf = NEW(more_foo);
more_foo_construct(new_mf, _foo, bar, more);
return new_mf;
}
foo *new_foo(int _foo, int bar)
{
foo *new_f = NEW(foo);
foo_construct(new_f, _foo, bar);
return new_f;
}
int main(void)
{
foo * mf = (foo*)new_more_foo(1, 2, 3);
foo * f = new_foo(7,8);
mf->printme(mf);
f->printme(f);
return 0;
}
printme() is overridden when creating "more foo". (polymorphism)
more_foo includes foo as a base structure (inheritance) so when "foo" structure changes, "more foo" changes with it (example new values added).
more_foo can be cast as "foo".
This doesn't work for foo
struct Foo;
typedef struct
{
int x;
}
Bar;
void foo (Foo *); // unknown type name ‘Foo’
void bar (Bar *);
typedef struct
{
int y;
}
Foo;
This doesn't work for bar
struct Foo;
typedef struct
{
int x;
}
Bar;
void foo (struct Foo *);
void bar (struct Bar *); ‘struct Bar’ declared inside parameter list
typedef struct
{
int y;
}
Foo;
Some of my structs have to be forward-declared, because they are passed as pointers, and some of them have to be not forward-declared, because they are passes as values.
Is there a way to declare types in C such that all function prototypes can consistently always refer to custom types in the same way, regardless of whether they are forward-declared or not?
Your problem is not forward-declared vs. non-forward-declared, it's struct X vs. typedef struct { ... } X.
You can solve this by using struct X only:
struct Foo;
struct Bar
{
int x;
};
void foo (struct Foo *);
void bar (struct Bar *);
struct Foo
{
int y;
};
Once you have that, you can introduce typedef names:
typedef struct Foo Foo;
typedef struct
{
int x;
}
Bar;
void foo (Foo *);
void bar (Bar *);
struct Foo
{
int y;
};
You can't pre-declare typedefs, so we still need a real struct type we can forward to. There's a small inconsistency here: Foo is the same as struct Foo, but there is no struct Bar, only Bar. You can fix that by switching to
typedef struct Bar
{
int x;
}
Bar;
This defines struct Bar and Bar simultaneously.
struct Foo;
Declare a structure named Foo. But, you must declare a typedef Foo of structure named Foo.
#include <stdio.h>
typedef struct Foo Foo;
typedef struct {
int x;
} Bar;
void foo(Foo *);
void bar(Bar *);
struct Foo {
int y;
};
int main(void) {
printf("Hello, world!\n");
}
The first order of business is to point out that in your examples there is no struct Foo. There is only a struct without a tag that you typedef as Foo.1
Is there a way to declare types in C such that all function prototypes can consistently always refer to custom types in the same way, regardless of whether they are forward-declared or not?
The definition or declaration of the struct should appear before the struct is used in a function parameter list. Otherwise the declarations scope is only the function prototype, which is almost certainly not what you want.
The way to achieve what you want is only through disciplined coding.
A forward declaration is all you ever really need for a function prototype. You don't need the full struct definition until the function itself is defined or called.
struct Foo;
void foo (struct Foo); // Okay, only at the call site or definition site
// do we need the full struct definition.
A short example to demonstrate
#include <stdio.h>
struct Foo;
void foo (struct Foo);
struct Foo
{
int y;
};
int main(void) {
struct Foo f = { .y = 1 };
foo(f);
return 0;
}
void foo (struct Foo f)
{
printf("%d", f.y);
}
It's much clearer that it's okay when the definitions and declarations are spread out among different translation units, but the above will have to do.
So what I suggest to you, is that you always forward declare your structs on a separate line, before they are to be used in function prototypes (by pointer or by value). And refrain from introducing the full definition until it's really needed.
1 A lovely correspondence on fa.linux.kernel where Linus Torvalds articulates far better than me why you should prefer to use the full struct tag.
The only "forward declaration" and reference supported by C is the pointer, e.g.:
void myFunc (struct XYZ *p);
This tells the compiler you are referring to a type struct XYZ, possibly not yet declared, of which you are passing a pointer. This allows the compiler to perform type checking without knowing what this structure actually consists of.
Note that pointers are all the same size, so there is no check on the pointer itself, just on the thing it is pointing to.
See also other solutions that explain using typedef.
You mix up forward declaration and type definitions. Both are different things. If you want to have the same kind of usage of forward declared structs do it:
struct Foo; // forward declaration
struct Bar { int x; }; // definition
void foo(struct Foo); // works for a prototype
void bar(struct Bar); // works for a prototype
You cannot forward declare type definitions. Maybe this is the reason for the name definition. However, you can type define a forward declaration:
struct Foo; // forward declaration
typedef struct Foo Foo_t; // type definition of a forward declaration
struct Bar { int x; }; // definition
typedef struct Bar Bar_t; // type definition of a definition
void foo(Foo_t); // works
void bar(Bar_t); // works
If you have a function definition the type has to be completed. This means that you have already defined the forward declared type at this location or that you have to use pointers. Again: It does not matter, whether you use structures or type definitions.
BTW: As you can see in my examples, it is an urban legend that incomplete structure types has to be passed "by reference". You can use the incomplete type in the function declaration (prototype). However, when you define the function, the type has to be completed. This is no deal in most cases.
I have a file in my project that has a local structure array defined like MyStruct_t myStruct[SIZE] which I can use well within that module. Now I would like to make it accessible to a different code module, so I came up with a function:
MyStruct_t *GetStruct(void) {
return myStruct;
}
But when I call this from my different module, I get an error expression must be a modifiable lvalue. My caller looks like:
void myFunc(void) {
MyStruct_t locStruct;
locStruct = GetStruct();
}
How can I do this best?
GetStruct returns a pointer to myStruct[SIZE] element, not a MyStruct_t. Unless you really need a copy, make locStruct a pointer, like this:
MyStruct_t *locStruct = GetStruct();
note that locStruct is an array of MyStruct_t, of size SIZE.
If you do want to make a copy, dereference GetStruct()'s result:
MyStruct_t locStruct = *GetStruct();
This would produce a copy of the initial element of myStruct array.
Since GetStruct does not provide additional services except accessing myStruct, you might as well make myStruct global (extern) instead of static.
Finally, you could change GetStruct to access a specific element. This would also take care of detecting overruns - i.e. attempts at getting an element past the SIZE or at a negative index:
bool GetStruct(int index, MyStruct_t *ptr) {
if (index < 0 || index >= SIZE) {
return false;
}
*ptr = myStruct[index];
return true;
}
Now the call of GetStruct() would look like this:
MyStruct_t locStruct;
if (GetStruct(5, &locStruct)) {
// All good
} else {
// Error
}
For example you can do the following way
void myFunc( void )
{
MyStruct_t locStruct[SIZE];
MyStruct_t *p = GetStruct();
memcpy( locStruct, p, SIZE * sizeof( MyStruct_t ) );
}
Or it might be enough to have a pointer to the first element of the array
void myFunc( void )
{
MyStruct_t *locStruct = GetStruct();
}
In this case the syntax for accessing elements of the array will be the same as for example locStruct[i]
GetStruct returns a pointer, so your locStruct variable should be a pointer, too.
void myFunc(void) {
MyStruct_t *locStruct;
locStruct = GetStruct();
}
If myStruct is global in the other module, then you might be looking for the extern keyword. Just put this in the other module:
extern MyStruct_t myStruct[];
(I've assumed MyStruct_t is a typedefed name. Otherwise you'd need to put the keyword struct before it, of course.)
This also requires access to the declaration of MyStruct. Put that in a header file and include it in both modules.
Here's a simple example:
// main.h ------------------------------------------------
typedef struct {
int a, b, c;
} AStruct;
// func.h ------------------------------------------------
void func(void);
// main.c ------------------------------------------------
#include <stdio.h>
#include "main.h"
#include "func.h"
AStruct as[100];
int main(void) {
func();
printf("%d,%d,%d\n", as[0].a, as[0].b, as[0].c);
return 0;
}
// func.c ------------------------------------------------
#include "main.h"
#include "func.h"
extern AStruct as[];
void func(void) {
as[0].a = 1;
as[0].b = 2;
as[0].c = 3;
}
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 have the following recursive type definitions in C and I am wondering how to get it to work:
typedef int (*foo) (bar *);
typedef foo *bar;
The sizes of the pointers are well known so this should be OK.
I somehow need to forward declare bar as some anonymous type that I can then typedef correctly. Not sure how to do this in C since it isn't a struct
I want to avoid declaring foo as:
typedef int (*foo) (void *)
because then I lose some type checking properties.
There is no forward declaration for typedefs in C, unfortunately.
UPD.
You can create indirectly recursive type as follows:
struct bar;
typedef int (*foo)(struct bar *);
struct bar {
foo f;
};
And then get pointer to function through the field of the argument. But this requires the structure to be allocated somewhere (may be on stack) and additional pointer dereferencing.
int boo(struct bar *bar) {
return (bar->f)(bar); // infinite loop
}
int main(void) {
struct bar baz = { &boo };
return boo(&baz);
}