Aliasing structs with pointers for const transitivity (C)

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

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

// [CODE BY FIPS @ 4FIPS.COM, (c) 2018 FILIP STOKLAS, MIT-LICENSED]

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...