Custom user-data reservation in ansi-c - c

I have a library with the following structure:
struct frame_meta_data
{
uint8_t id;
uint8_t general_field_1;
uint8_t general_field_2;
...
uint8_t user_data[16];
};
And I would like users of the library to be able to save custom data into frame objects (that's what the user_data field is for).
However when trying to cast user_data into a custom structure:
frame_meta_data cur_frame;
...
#define USER_HDR ((struct my_user_header*)cur_frame.user_data)
I get the following error:
warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
#define USER_HDR ((struct my_user_header*)cur_frame.user_data)
How can I work around this?
Thanks in advance.

Reinterpreting addresses like that isn't allowed by the C standard. Strict aliasing means that compilers are free to assume two pointers of different types will never point at the same object, and then make all sorts of optimizations based of that.
Your code violates the C standard and has undefined behavior on account of that. But you can fix it still. Like melpomene suggested in the comments, don't cast, but use memcpy:
struct my_user_header obj;
memcpy(&obj, cur_frame.user_data, sizeof obj);
Alternatively, some compilers allow you to write non-standard code with compiler option, such as GCC's -fno-strict-aliasing.

If you know what you are doing, you can disable that warning. There is however a potential problem.
Assume that the structure you want to use contains something that is larger than 1 byte. For example a 4-byte integer. Now if you simply cast that user_data field to your structure it is possible that the int is not aligned to 4-byte boundary as it should be. This might result in a runtime exception in some architectures.
Using memcpy should solve that problem though. And remove the warning.

I suspect it's because you're involving copies of this USR_DATA macro expression in multiple accesses to the data area, and it's confusing the compiler. Or perhaps you're even mixing USR_DATA accesses with manipulations of the underlying char array.
If the data area is only being initialized and accessed as that given user data type, there isn't any aliasing going on. Ensure you use it that way.
I would provide an external (as in, non-inlined, external linkage) API function which, given a frame object, returns a void * to the associated user data:
struct foobar *fbs = (struct foobar *) frame_get_userdata(fr);
// now work just with fbs
The cast isn't necessary; that's my style.
Depending on what precedes the user data, it might not be suitably aligned for arbitrary use. One easy way to fix that would be to make it the first struct member, if that option is available. Otherwise there are various fairly portable tricks involving making a union between a char array and various types like long double and whatnot, or else using compiler-specific constructs, like __attribute__((aligned)) with GCC.

Related

MISRA-C: Is it safe to cast a char array to a structure pointer?

When I have a user defined type like the following:
typedef struct MyData_t {
uint16_t val;
...
} MyData;
And a simple array that I want to use to store different types of structures in:
uint8_t buffer[];
And I then want to create a structure pointer that uses the array to store the data of that structure:
MyData* freelist = (MyData*) buffer;
Then I get the MISRA 2012 Error:
Note 9087: cast performed between a pointer to object type and a pointer to a different object type [MISRA 2012 Rule 11.3, required]
This rule says because of possible alignment issues it is never safe to cast pointers between different types of objects.
My question is: How common is it in an embedded environment for compilers to cause any issues in this case? And how could I prevent these issues when forced to keep the implementation concept (about the buffer array that stores different types of objects)?
If you dereference freelist then you invoke undefined behavior. Both because of possible alignment issues as well as strict aliasing. It's a bug, MISRA or no MISRA. The easiest fix is to use memcpy instead.
How common is it in an embedded environment for compilers to cause any issues in this case?
In case of alignment, it depends on the hardware. Some architectures like MIPS are very picky with alignment, others like generic 8-bitter MCUs couldn't care less.
As for strict aliasing bugs, it was common for the gcc compiler to go haywire upon strict aliasing violations at the time it started to gain popularity in embedded systems, somewhere around the beginning of the ARM hype year 2008-2010 somewhere (gcc versions around 3.x something?). Modern gcc versions have less strict aliasing mis-optimizations. Still always compile with -fno-strict-aliasing when using gcc, since the compiler is instable and generally dangerous to use when strict aliasing is allowed.
As for the regular embedded systems compilers, they are usually not as stupid as to abuse strict aliasing optimizations since they want to sell their compilers.
Notably, the other way around - going from struct to character pointer - is fine. MISRA C:2012 11.3 then lists the following explicit exception:
Exception
It is permitted to convert a pointer to object type into a pointer to one of the object types char, signed char or unsigned char.
EDIT
If it's ok to break a few advisory MISRA rules like casting between integers and pointers, then perhaps something like the example below could be an option. No pointer conversions, no pointer arithmetic, no strict aliasing problems. You'll have to cast the integer into a struct pointer type on the caller side, which violates advisory rules. You have to set aside an aligned chunk of data at the address of mempool_addr with size mempool_maxsize in your linker script.
#include <stdint.h>
#include <stddef.h>
#define mempool_maxsize 1024u
#define mempool_addr 0x10000u
static size_t mempool_size=0u;
uintptr_t static_alloc (size_t size)
{
uintptr_t result;
if(mempool_size + size > mempool_maxsize)
{
return 0;
}
if((size % _Alignof(int)) != 0)
{
size += _Alignof(int) - (size % _Alignof(int));
}
result = mempool_addr + mempool_size;
mempool_size += size;
return result;
}
How common is it in an embedded environment for compilers to cause any issues in this case?
Common enough as it fails to meet alignment needs. E. g. buffer[] may exist on an odd address and access to uint16_t needs an even one. Result: bus violation. Any casting will not help.
how could I prevent these issues
Use a union of uint8_t[] and struct MyData_t to align and avoid aliasing issues too.
Various ways to insure uint8_t buffer[] is aligned well. Example:
#include <stddef.h>
#define BUF_N 100
union {
uint8_t buffer[BUF_N];
max_align_t a; // Or any wide type like complex long double
} u;
And use u.buffer instead of buffer.
Also research _Alignas
The rationale for this Rule is actually the same for restricting the use of unions - there are many pitfalls for the unwary.
Alignment, as discussed, is probably the primary issue
Strict aliasing, again as mentioned
Padding within the structure, is another
If you take appropriate steps to (a) ensure alignment and (b) ensure the packing/unpacking in to and out of the structure is correct, and (c) ensuring you do not violate the strict aliasing considerations, you could probably get away with it.
You could, of course, disapply R.18.1 and use a union of myData_t myData and uint8_t data[]...
But frankly, you'd probably be better off explicitly unpacking the data field by field.
See profile for affiliations
You can probably circumvent the error through first casting it to a void* pointer.
That being said, it is still implementation defined behaviour and therefore goes against MISRA guidelines. You are only guaranteed validity as per the standard if you cast to void* and back to the exact same type.
However, there may often be cases in embedded systems where this is needed, eg. to access specific memory areas. I have had some at least. In these cases you'd need to have this use signed-off by management as per MISRA.

What does *(void **) (&funcp) do in this line of code involving dlsym()?

Could somebody help me interpret this line of code (from here)?
*(void **) (&funcp) = dlsym(libHandle, argv[2]);
I do not understand what *(void **) (&funcp) does.
This might clarify it (from here):
(Update: I didn't include the exact same link to be snarky. I missed the link in the original question. :P)
/* The rather clumsy cast above is necessary because the ISO C standard
does not require that pointers to functions can be cast back and
forth to 'void *'. (See TLPI pages 863-864.) SUSv3 TC1 and SUSv4
accept the ISO C requirement and propose casts of the above
form as the workaround. However, the 2013 Technical Corrigendum
(TC1) to SUSv4 requires casts of the following more natural form
to work correctly:
funcp = (void (*)()) dlsym(libHandle, argv[2]);
Various current compilers (e.g., gcc with the '-pedantic' flag)
may still complain about such casts, however. */
It's basically a hack to avoid having to cast the void* from dlsym() to a function pointer, by instead reinterpreting the data in funcp as a void* and storing into that. This is done by taking the address of funcp (the address of the variable itself), pretending that the address refers to a void* (via the (void**) cast), dereferencing it, and storing the void* from dlsym() into it. Simpler forms are likely to work in practice too.
This method of "reinterpreting" data by taking its address, casting that address to a pointer to a different type, and dereferencing, is often called type punning by the way. The pun comes from the same data having different meanings when interpreted in different ways, which is how real puns work too.
(Type punning can be unsafe in certain circumstances, including when the compiler makes use of strict aliasing rules, which lets it assume that certain pointers of different type do not alias (that they do not refer to the same data). The cast above might violate strict aliasing as you get a function pointer and a void* referring to the same data, though it's a "likely to work in practice" thing in this case.)
(The reason ISO C does not require that function pointers can be safely cast to void pointers and back is probably that functions and data (void pointers refer to "data") are stored separately on some machines. Since they are separate, they might also use different address lengths or formats, so that casting between function pointers and data pointers might not make sense. Architectures that separate code and data in that way are called Harvard architectures.)
dlsym() relates to dlopen() and dlclose() See the man pages.
The line you're seeing it is looking up a symbol (fetching the value of the symbol, and in this case is presuming it is a function address), in the binary object loaded at dlopen(), and assigning it to the pointer variable funcp.
When funcp is typecast to the corresponding function type, meaning given the proper function signature, that function can be called via funcp and parameters passed as well.
dl (dynamic library) set of functions are the mechanism by which plugins are typically facilitated on systems that support dlopen/dlsym/dlclose. The plugin has to conform to an interface defined by the user, or community, that the code that wants to load the plugin must also know, so that knows how to find and define the symbols by name, and how to cast them and use them.
Another way of putting it, is it lets you make calls into an object that isn't available at link time and lets your code do at runtime what the linker handles for you at link time.
dlsym() returns a (void *) because it can't assume anything about the symbol it's loading, which could be a variable, a function entry point, etc... to do anything with the value returned, you generally need to cast it into the type that corresponds to the symbol in the binary loaded with dlopen().

multilevel inheritance in c

when doing inheritance in pure C like this
typedef struct {
char name[NAMESIZE];
char sex;
} Person;
typedef struct {
Person person;
char job[JOBSIZE];
} Employee;
typedef struct {
Person person;
char booktitle[TITLESIZE];
} LiteraryCharacter;
I know it is okay to cast a instance of type "LiteraryCharacter" to type "Person", and use it as such. But is it also ok/safe to cast a instance of type "LiteraryCharacter" to type "Employee" and use it as such?
Such a cast is undefined behavior in standard C, although it will work with many compilers.
Even if it works on a compiler you are currently using, be aware that it might break in a future version of the compiler, or with a different compiler. The C standard allows the compiler to assume that pointers to different types don't point to the same memory - except for some well-documented exceptions, which include cast of LiteraryCharacter * to Person *. The code that casts LiteraryCharacter * to Employee * can and will break under a compiler that makes use of this assumption to generate efficient code.
It might be a good idea to explain why you think you need this cast in the first place. Its equivalent would be quite incorrect in C++, and generate a ClassCastException in Java. After all, LiteraryCharacter doesn't have the fields of Person, such as job.
That would be undefined behaviour. There is no such thing as inheritance in C.
You might get away with it if the structures had exactly the same layout but that would be very brittle code indeed.
Undefined behavior:
In your example you are casting to-from incompatible types which doesn't even compile because of the differences in the sizes of those two types. You can however cast to-from compatible (or even incompatible) pointer types and it will compile.
Casting to-from incompatible (or rather pseudo-compatible) types is undefined behavior, on some structures and compiler implementations it will work on others it won't.
Casting to compatible -- pointer types is safe as long as the compiler is taking care of the object structure / internal alignments / memory layout, etc. (there's an example below).
The "OK" part is debatable. Will it work? Yes because they have the same "in memory" layout and you are aware of that particular fact. But what happens when another programmer created that structure? You have to read its source to assess if it can be safely cast to another type.
Encapsulation and future proofing:
Also most encapsulation techniques will only expose an "opaque type" which you can use via pointers -- pass it along to functions implemented within the same library/package and they do all of the structure specific work. In the case of "opaque types" you only know that that structure exists, you don't know it's internal structure so you can't just change the pointer type you're using to access it because you can't be sure of the structure compatibility behind it.
The point of encapsulation is to allow modules to be developed individually. So when the original developer of this external module changes the structure in a future version it breaks compatibility with your code (which shouldn't be using it that way anyway).
Safer way to do this:
This is a non standard (yet pretty much ubiquitous) compiler feature of GCC.
typedef struct {
char name[NAMESIZE];
char sex;
} Person;
typedef struct {
Person;
char job[JOBSIZE];
} Employee;
typedef struct {
Employee;
char booktitle[TITLESIZE];
} LiteraryEmployeeCharacter;
LiteraryEmployeeCharacter* lec = malloc(sizeof(LiteraryEmployeeCharacter));
lec->name = "My character";
lec->sex = 'F';
lec->job = "Steward";
lec->booktitle = "A book";
By using unnamed fields you get access to name, sex and job as if they were defined in the LiteraryEmployeeCharacter structure.
By casting to a compatible pointer type the compiler knows the exact structure and position of every field and ca easily handle the structure correctly.

Extending a struct in C

I recently came across a colleague's code that looked like this:
typedef struct A {
int x;
}A;
typedef struct B {
A a;
int d;
}B;
void fn(){
B *b;
((A*)b)->x = 10;
}
His explanation was that since struct A was the first member of struct B, so b->x would be the same as b->a.x and provides better readability.
This makes sense, but is this considered good practice? And will this work across platforms? Currently this runs fine on GCC.
Yes, it will work cross-platform(a), but that doesn't necessarily make it a good idea.
As per the ISO C standard (all citations below are from C11), 6.7.2.1 Structure and union specifiers /15, there is not allowed to be padding before the first element of a structure
In addition, 6.2.7 Compatible type and composite type states that:
Two types have compatible type if their types are the same
and it is undisputed that the A and A-within-B types are identical.
This means that the memory accesses to the A fields will be the same in both A and B types, as would the more sensible b->a.x which is probably what you should be using if you have any concerns about maintainability in future.
And, though you would normally have to worry about strict type aliasing, I don't believe that applies here. It is illegal to alias pointers but the standard has specific exceptions.
6.5 Expressions /7 states some of those exceptions, with the footnote:
The intent of this list is to specify those circumstances in which an object may or may not be aliased.
The exceptions listed are:
a type compatible with the effective type of the object;
some other exceptions which need not concern us here; and
an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union).
That, combined with the struct padding rules mentioned above, including the phrase:
A pointer to a structure object, suitably converted, points to its initial member
seems to indicate this example is specifically allowed for. The core point we have to remember here is that the type of the expression ((A*)b) is A*, not B*. That makes the variables compatible for the purposes of unrestricted aliasing.
That's my reading of the relevant portions of the standard, I've been wrong before (b), but I doubt it in this case.
So, if you have a genuine need for this, it will work okay but I'd be documenting any constraints in the code very close to the structures so as to not get bitten in future.
(a) In the general sense. Of course, the code snippet:
B *b;
((A*)b)->x = 10;
will be undefined behaviour because b is not initialised to something sensible. But I'm going to assume this is just example code meant to illustrate your question. If anyone's concerned about it, think of it instead as:
B b, *pb = &b;
((A*)pb)->x = 10;
(b) As my wife will tell you, frequently and with little prompting :-)
I'll go out on a limb and oppose #paxdiablo on this one: I think it's a fine idea, and it's very common in large, production-quality code.
It's basically the most obvious and nice way to implement inheritance-based object oriented data structures in C. Starting the declaration of struct B with an instance of struct A means "B is a sub-class of A". The fact that the first structure member is guaranteed to be 0 bytes from the start of the structure is what makes it work safely, and it's borderline beautiful in my opinion.
It's widely used and deployed in code based on the GObject library, such as the GTK+ user interface toolkit and the GNOME desktop environment.
Of course, it requires you to "know what you're doing", but that is generally always the case when implementing complicated type relationships in C. :)
In the case of GObject and GTK+, there's plenty of support infrastructure and documentation to help with this: it's quite hard to forget about it. It might mean that creating a new class isn't something you do just as quickly as in C++, but that's perhaps to be expected since there's no native support in C for classes.
That's a horrible idea. As soon as someone comes along and inserts another field at the front of struct B your program blows up. And what is so wrong with b.a.x?
Anything that circumvents type checking should generally be avoided.
This hack rely on the order of the declarations and neither the cast nor this order can be enforced by the compiler.
It should work cross-platform, but I don't think it is a good practice.
If you really have deeply nested structures (you might have to wonder why, however), then you should use a temporary local variable to access the fields:
A deep_a = e->d.c.b.a;
deep_a.x = 10;
deep_a.y = deep_a.x + 72;
e->d.c.b.a = deep_a;
Or, if you don't want to copy a along:
A* deep_a = &(e->d.c.b.a);
deep_a->x = 10;
deep_a->y = deep_a->x + 72;
This shows from where a comes and it doesn't require a cast.
Java and C# also regularly expose constructs like "c.b.a", I don't see what the problem is. If what you want to simulate is object-oriented behaviour, then you should consider using an object-oriented language (like C++), since "extending structs" in the way you propose doesn't provide encapsulation nor runtime polymorphism (although one may argue that ((A*)b) is akin to a "dynamic cast").
I am sorry to disagree with all the other answers here, but this system is not compliant to standard C. It is not acceptable to have two pointers with different types which point to the same location at the same time, this is called aliasing and is not allowed by the strict aliasing rules in C99 and many other standards. A less ugly was of doing this would be to use in-line getter functions which then do not have to look neat in that way. Or perhaps this is the job for a union? Specifically allowed to hold one of several types, however there are a myriad of other drawbacks there too.
In short, this kind of dirty casting to create polymorphism is not allowed by most C standards, just because it seems to work on your compiler does not mean it is acceptable. See here for an explanation of why it is not allowed, and why compilers at high optimization levels can break code which does not follow these rules http://en.wikipedia.org/wiki/Aliasing_%28computing%29#Conflicts_with_optimization
Yes, it will work. And it is one of the core principle of Object Oriented using C. See this answer 'Object-orientation in C' for more examples about extending (i.e inheritance).
This is perfectly legal, and, in my opinion, pretty elegant. For an example of this in production code, see the GObject docs:
Thanks to these simple conditions, it is possible to detect the type
of every object instance by doing:
B *b;
b->parent.parent.g_class->g_type
or, more quickly:
B *b;
((GTypeInstance*)b)->g_class->g_type
Personally, I think that unions are ugly and tend to lead towards huge switch statements, which is a big part of what you've worked to avoid by writing OO code. I write a significant amount of code myself in this style --- typically, the first member of the struct contains function pointers that can be made to work like a vtable for the type in question.
I can see how this works but I would not call this good practice. This is depending on how the bytes of each data structure is placed in memory. Any time you are casting one complicated data structure to another (ie. structs), it's not a very good idea, especially when the two structures are not the same size.
I think the OP and many commenters have latched onto the idea that the code is extending a struct.
It is not.
This is and example of composition. Very useful. (Getting rid of the typedefs, here is a more descriptive example ):
struct person {
char name[MAX_STRING + 1];
char address[MAX_STRING + 1];
}
struct item {
int x;
};
struct accessory {
int y;
};
/* fixed size memory buffer.
The Linux kernel is full of embedded structs like this
*/
struct order {
struct person customer;
struct item items[MAX_ITEMS];
struct accessory accessories[MAX_ACCESSORIES];
};
void fn(struct order *the_order){
memcpy(the_order->customer.name, DEFAULT_NAME, sizeof(DEFAULT_NAME));
}
You have a fixed size buffer that is nicely compartmentalized. It sure beats a giant single tier struct.
struct double_order {
struct order order;
struct item extra_items[MAX_ITEMS];
struct accessory extra_accessories[MAX_ACCESSORIES];
};
So now you have a second struct that can be treated (a la inheritance) exactly like the first with an explicit cast.
struct double_order d;
fn((order *)&d);
This preserves compatibility with code that was written to work with the smaller struct. Both the Linux kernel (http://lxr.free-electrons.com/source/include/linux/spi/spi.h (look at struct spi_device)) and bsd sockets library (http://beej.us/guide/bgnet/output/html/multipage/sockaddr_inman.html) use this approach. In the kernel and sockets cases you have a struct that is run through both generic and differentiated sections of code. Not all that different than the use case for inheritance.
I would NOT suggest writing structs like that just for readability.
I think Postgres does this in some of their code as well. Not that it makes it a good idea, but it does say something about how widely accepted it seems to be.
Perhaps you can consider using macros to implement this feature, the need to reuse the function or field into the macro.

Is typedef'ing a pointer type considered bad practice? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Typedef pointers a good idea?
I've seen this oddity in many APIs I have used:
typedef type_t *TYPE;
My point is that declaring a variable of type TYPE will not make it clear that in fact a pointer is declared.
Do you, like me, think that this brings a lot of confusion? Is this meant to enforce encapsulation, or there are other reasons as well? Do you consider this to be a bad practice?
In general, it's a bad practice. The significant problem is that it does not play well with const:
typedef type_t *TYPE;
extern void set_type(TYPE t);
void foo(const TYPE mytype) {
set_type(mytype); // Error expected, but in fact compiles
}
In order for the author of foo() to express what they really mean, the library that provides TYPE must also provide CONST_TYPE:
typedef const type_t *CONST_TYPE;
so that foo() can have the signature void foo(CONST_TYPE mytype), and at this point we have descended into farce.
Hence a rule of thumb:
Make typedefs of structs (particularly incomplete structs), not pointers to those structs.
If the definition of the underlying struct is not to be publicly available (which is often laudable), then that encapsulation should be supplied by the struct being incomplete, rather than by inconvenient typedefs:
struct type_t;
typedef struct type_t type_t;
void set_type(type_t *);
int get_type_field(const type_t *);
A common idiom is to suffix the type with _p to indicate that it's a pointer while still retaining the pointery qualities.
Sometimes it is necessary to use only the pointer type if the struct that it is pointing to is not publicly available. This helps facilitate data hiding. I.e.
typedef struct hidden_secret_object * object;
void change_object(object foo);
this allows you to change the way that hidden_secret_object is structured without breaking external code.
I don't find it clear either. I'm not fond of full capitalised types either (I try to reserve those for #defines).
This way makes it easy to kid oneself by thinking it is in fact a value type, while we're talking about a pointer type. The pointer type can be completely abstracted away with smart pointers, but that isn't common practise in C.
Suffixing with (as mentioned previously) _p, _ptr, Pointer or anything along those lines creates clarity; increases typing, that's true, but will prevent you from silly mistakes (such as using '.' instead of '->', ...) costing you valuable developing time.
It depends on what you are trying to achieve. There is no meaningful "yes or no" answer to your question the way it is stated.
If you are trying to create an abstract handle kind of type, implying that the user is not supposed to know or care what is hiding behind the type, then typedef-ing a pointer type is perfectly fine. The whole point is that today it might be a pointer type, and tomorrow it might become an integer type, and later it might become something else. This is exactly what pointer type typedefs are normally used for in most library interfaces.
You are saying that sometimes it is "not clear that a pointer is declared". But under this usage model that's exactly the point! It is supposed to be "not clear". The fact that the type happens to be an obfuscated pointer is none of your business. It is something that you don't need to know and not supposed to rely upon.
A classic example of this usage model is the va_list type in the standard library. In some implementation it might easily be a typedef for a pointer type. But that's something you are not supposed to know or rely upon.
Another example would be the definition of HWND type in Windows API. It is a typedef for pointer type as well, but that's none of your business.
A completely different situation is when you are typedef-ing a pointer type as a form of shorthand, just to make the declarations shorter for not having to type the * character every time. In this case the fact that the typedef is (and will always be) standing for a pointer type is exposed to the user. Normally this usage is not a good programming practice. If the users will want to create an alias to avoid typing * every time, they can do it by themselves.
This usage model usually leads to more obfuscated code for the reasons you already mentioned in your OP.
Example of this bad usage of typedefs can also be found in Windows API. Typedef names like PINT follow exactly that flawed usage model.
I don't think it's bad practice if the it's a pointer to an incomplete type, or if for any other reason the user isn't expected to dereference it. I never understood FILE*.
I also don't think it's bad practice if you're doing it because you have several levels of indirection, and you want to use it in situations where some of them are irrelevant. typedef char **argarray, or something.
If the user is expected to dereference it then in C, I think it's probably best to retain the *. In C++, people are used to user-defined types with overloaded operator*, such as iterators. In C that's just not normal.
Storage-class qualifiers like 'const' will work differently with typedef'ed pointers than with 'natural' ones. While this isn't typically a good thing with 'const', it can be very useful with compiler-specific storage classes like "xdata". A declaration like:
xdata WOKKA *foo;
will declare "foo" to be a pointer, stored in the default storage class, to a WOKKA in xdata. A declaration:
xdata WOKKA_PTR bar;
would declare "bar" to be a pointer, stored in xdata, to a WOKKA in whatever storage class was specified in WOKKA_PTR. If library routines are going to expect pointers to things with a particular storage class, it may be useful to define those storage classes within the pointer types.
It's bitten me in the ass on occasion:
for (vector<typedef_name_that_doesnt_indicate_pointerness_at_all>::iterator it;
it != v.end(); ++it)
{
it->foo(); // should have been written (*it)->foo();
}
The only time it's acceptable is if the type is meant to be truly opaque and not accessed directly at all. IOW, if someone's going to have to dereference it outside of an API, then the pointerness should not be hidden behind a typedef.
Maybe a way to make it more specific would be to call the new pointer type type_ptr or something like that:
typedef type_t* type_ptr;

Resources