Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to trigger implicit pointer conversion inline in a C macro?

Context

I have some functions to support using a custom memory allocator in my library:

void *(allocate)(struct allocator *allocator, size_t size, size_t alignment);
void (deallocate)(struct allocator *allocator, void *pointer, size_t size, size_t alignment);

There’s two things that I would still like to improve upon with this interface:

  1. There is a need to write sizeof(type) and alignof(type) for every allocation and deallocation.
  2. The type void * allows mistakenly using a pointer to a type with invalid size or alignment.

Both of these can be fixed with some simple macros:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#define allocate(allocator, type, count) \
    (type *)(allocate)(allocator, sizeof(type) * (count), alignof(type))

#define deallocate(allocator, pointer, type, count) \
    do { \
        type *typed_pointer = pointer; \
        (deallocate)(allocator, typed_pointer, sizeof(type) * (count), alignof(type)); \
    } while (0)

The macro takes care of calling sizeof(type) and alignof(type), and also performs a cast of the pointer to the given type so the compiler issues a warning when it is used as a different type.

Problem

deallocate does not have a return value, so we can implement it as a block with a variable to perform the implicit pointer cast. But for a function that does return a value, maybe reallocate, we cannot type check the pointer that is passed to the macro in the same way.

Is there any way to perform this "type checking" implicit cast inline inside of an expression, such that the macro can have a result?

EDIT: I would like to stick to standard C without any GNU or other extensions, if possible.

>Solution :

Compound literals are objects that can be assigned to, so you can write (type *) {0} = (pointer) as the argument to reallocate, and the compiler will do its usual checks for assignment to a pointer type. The value of the assignment expression will be the new value assigned to the compound literal.

Not all types can be handled this way, as appending *to a type does not necessarily yield a pointer to that type. For example, int [] would produce int [] *, which will not work. You already have that problem for the (type *) cast on allocate. The user could use a typedef for any type, though, and then pass the typedef name.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading