I'm proposing a change to a library whose public API currently looks like this:
typedef size_t enh; /* handle */
int en_open(enh *handle)
{
struct internal *e = malloc(...);
*handle = (enh)e;
return 0;
}
int en_start(enh handle)
{
struct internal *e = (struct internal*)handle;
return do_something(e);
}
Does this usage, casting back and forth to size_t
break strict aliasing?
For the record, I'm proposing a typical opaque forward declaration of struct internal
in the public API, as shown on this Programmers.SE question about the same code.
Aliasing is about two pointers of different type being used to access the same bytes. This is not the case in your code. When you access the data members behind the handle, you always do it via a pointer of type struct internal*
. So no harm here.
The only questionable thing in your code is, that you are using size_t
to pass the pointer. Afaik, the standard does not guarantee that you can safely cast a pointer to size_t
and back, even though any sane implementation will allow it. The correct integer type choice would be uintptr_t
, but you don't even need that:
I think, you should just use an opaque pointer in the interface. I. e., just put the declaration
typedef struct internal internal;
into your public header and keep the corresponding
struct internal {
...
}
private (replacing internal
with a sensible public name, of course). The public functions can then simply be declared as:
int en_open(internal** outHandle);
int en_close(internal* handle);
That way, you get perfect type checking in the client code, and avoid the need for any casts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With