Aliasing structs with pointers for const transitivity (C)

> Coding, hacking, computer graphics, game dev, and such...
User avatar
Site Admin
Posts: 169
Joined: Wed Nov 12, 2008 9:49 pm
Location: Prague

Aliasing structs with pointers for const transitivity (C)

Post by fips »

This is just a quick brain dump, something I've been experimenting a lot recently in my toy C project. The code below shows how to compose two aliasing views (constant and mutable) on the same object, which is mostly useful for structs with pointers. The motivation behind this construct is to get full constness when casting from mutable objects to const ones, meaning not only the values of nested pointers become const, but also the referenced data. The code below shows the concept:

Code: Select all


typedef struct my_buf_c_s {
    const uint8_t *data;
    size_t size;
} my_buf_c;

typedef struct my_buf_s {
    union {
        struct {
            uint8_t *data;
            size_t size;
        my_buf_c const_view;
} my_buf;

#define MY_CONST_CAST(ptr) (&(ptr)->const_view)

void my_buf___mutable_func(my_buf *buf) {
    buf->data[0] = 5; // OK: read-write location 'uint8_t *data'
    buf->data = NULL; // OK: read-write object 'uint8_t *data'
    buf->size = 0;    // OK: read-write object 'size_t size'

void my_buf___constant_func(const my_buf_c *buf) {
    buf->data[0] = 5; // error: read-only location 'const uint8_t *const data'
    buf->data = NULL; // error: read-only object 'const uint8_t *const data'
    buf->size = 3;    // error: read-only object 'const size_t size'

int main() {
    uint8_t tmp[] = { 0, 1, 2 };
    my_buf buf = { .data = tmp, .size=3 };
    my_buf___constant_func(&buf); // error: expected 'const my_buf_c *'
    my_buf___constant_func(MY_CONST_CAST(&buf)); // OK
    my_buf___mutable_func(&buf); // OK
    return 0;
I'm still not sure if I like it, but it has proved quite useful and scalable as it's pretty easy to build 2 aliasing hierarchies of nested structs, one mutable the other const.

Follow the discussion on Reddit...