Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does casting a pointer back and forth from size_t or uintptr_t break strict aliasing?

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.

like image 403
Jonathon Reinhart Avatar asked Aug 28 '15 21:08

Jonathon Reinhart


1 Answers

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.

like image 199
cmaster - reinstate monica Avatar answered Oct 24 '22 11:10

cmaster - reinstate monica