There are two main ways to keep the size of a pointer.One as just another variable along side:size_t length = get_length();int* stuff = (int*) malloc(length * sizeof(int));do_stuff(stuff, length);Another is a struct:typedef struct ptr_with_length {     void* ptr;    size_t length;} ptr_with_length;size_t length = get_length();ptr_with_length stuff = { malloc(length * sizeof(int)), length };do_stuff(length);But another way is storing the size of the pointer at the beginning of the pointer:size_t length = get_length();size_t* stuff = malloc(length * sizeof(int) + sizeof(size_t));stuff[0] = length;do_stuff((int*) (stuff + 1))I wrote some functions which are basically wrappers around the stdlib functions to do this:sptr.h#ifndef SPTR_H#define SPTR_H#include <stdlib.h>void* make_sptr(void* ptr, size_t size);void* make_ptr(void* sptr);void free_sptr(void* sptr);void* malloc_sptr(size_t size);void* realloc_sptr(void* sptr, size_t size);void* calloc_sptr(size_t nitems, size_t size);size_t sptr_size(void* sptr);void* rel_realloc_sptr(void* sptr, long long int relative_size);#endif // SPTR_Hsptr.c#include <string.h>#include sptr.h/** * Make a sptr from a regular pointer. Invalidates the pointer. * * @param ptr A pointer to a block of memory with `size` bytes allocated * @param size The size (in bytes). * @return NULL on error (With original pointer untouched), otherwise a new sptr. */void* make_sptr(void* ptr, size_t size) {    size_t* sptr = (size_t*) realloc(ptr, size + sizeof(size_t));    if (sptr == NULL) {        return NULL;    }    memmove(sptr + 1, sptr, size);    sptr[0] = size;    return sptr + 1;}/** * Make a regular pointer from a sptr that can be used by `free()`, `realloc()` and friends. Invalidates `sptr`. */void* make_ptr(void* sptr) {    size_t size = sptr_size(sptr);    memmove(sptr, ((size_t*) sptr) - 1, size);    void* ptr = realloc(((size_t*) sptr) - 1, size);    if (ptr == NULL) {        return ((size_t*) sptr) - 1;    }    return ptr;}/** * Frees the memory allocated to a sptr. Like `free(ptr)`, but for sptrs. */void free_sptr(void* sptr) {    free(((size_t*) sptr) - 1);}/** * Allocates a block of memory, and returns the pointer to the beginning of the memory. * Like `malloc(size)`, but for sptrs. * * @param size The number of bytes to allocated. * @return NULL if no memory is available, otherwise a pointer with `size` bytes of memory allocated. */void* malloc_sptr(size_t size) {    size_t* sptr = (size_t*) malloc(size + sizeof(size_t));    if (sptr == NULL) {        return NULL;    }    sptr[0] = size;    return sptr + 1;}/** * Resize the amount of memory allocated to a pointer. Like `realloc(ptr, size)`, but for sptrs. * Invalidates the original sptr on success. * * @param sptr The sptr to resize * @param size The new number of bytes to allocate * @return NULL if the reallocation was unsuccessful (With the input sptr untouched), a new sptr otherwise. */void* realloc_sptr(void* sptr, size_t size) {    size_t* new_sptr = (size_t*) realloc(((size_t*) sptr) - 1, size + sizeof(size_t));    if (new_sptr == NULL) {        return NULL;    }    new_sptr[0] = size;    return new_sptr + 1;}/** * Like `malloc_sptr(nitems * size)`, but sets all the allocated bytes to 0. Like `calloc(nitems, size)`, but for sptrs. * * @param nitems The number of items to set. * @param size The size of each item (e.g. `sizeof(int)`). * @return NULL if no memory is available, the pointer to the begining of a block of memory otherwise. */void* calloc_sptr(size_t nitems, size_t size) {    size_t* sptr = (size_t*) calloc(nitems * size + sizeof(size_t), 1);    if (sptr == NULL) {        return NULL;    }    sptr[0] = nitems * size;    return sptr + 1;}/** * Returns the size of the `sptr`. */size_t sptr_size(void* sptr) {    return *(((size_t*) sptr) - 1);}/** * Reallocates memory, adding or subtracting allocated bytes relative to the current size. * * If the new size would be negative, zero bytes are allocated. Invalidates the original sptr on success. * * @param sptr The sptr to resize * @param relative_size The number of bytes to add (Or subtract if negative) * @return NULL if the reallocation was unsuccessful (With the input sptr untouched), a new sptr otherwise. */void* rel_realloc_sptr(void* sptr, long long int relative_size) {    long long int new_ssize = (long long int) sptr_size(sptr) + relative_size;    size_t new_size = new_ssize < 0 ? 0U : (size_t) new_ssize;    size_t* new_sptr = (size_t*) realloc(((size_t*) sptr) - 1, new_size + sizeof(size_t));    if (new_sptr == NULL) {        return NULL;    }    new_sptr[0] = new_size;    return new_sptr + 1;}The functions defined are:make_sptr which takes a regular pointer, reallocs enough for a size_t, moves over all of the data, writes the size, and returns the pointer offset past the size.make_ptr which moves the data in the sptr to where the size_t was and truncates it to the size. Currently, it returns the same sptr offset to the beginning if realloc to truncate it fails (Which it apparantly can in places where realloc is just malloc + memmove + free). Should this just return NULL? Currently, the only difference between a failure of realloc and a success is accessing past the intended length will be garbage instead of a potential seg fault. I think this behaviour is acceptable, as those addresses shouldn't be accessed anyways. Since it is a corner case (Bad realloc implementation for shrinking and out of memory), the slightly extra memory usage of 1 size_t shouldn't be too much of a problem.free_sptr, a wrapper around free.malloc_sptr, a wrapper around malloc.realloc_sptr, a wrapper around realloc.calloc_sptr, a wrapper around calloc.sptr_size which retrieves the size of the allocated memory.rel_realloc_sptr which is like realloc, but relative to the current size. What type should I use for the relative size? I am currently using a long long int for the difference between two size_ts. Maybe ptrdiff_t? However, since I am not accounting for any sort of overflow (as not that much memory should be allocated in the first place), maybe this is unneccesary, and I should use a int instead.You should be able to do normal pointer stuff, like sizeof, arithmetic and memcopy, strlen, etc..I am looking for comments on style, answers to the questions above and whether this could be used as a library (Else what would need to be changed before it could be).As for correctness, the following is an excerpt from The C99 standard (WG14/N1124. Committee Draft -- May 6, 2005. ISO/IEC 9899:TC2) about free() (Page 325):if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.Since adding a constant sizeof(size_t) and then subtracting it will match the one returned by realloc, this is fine:void* test = ++malloc(100);  // Ignoring NULL for thisfree(test - 1);// Matches (is equal to) the original pointer// returned by malloc; works as expected.Some example usage of this:#include <stdio.h>#include sptr.hvoid print_int_sptr(int* sptr);  // To appease GCCs -Werror=missing-declarationvoid print_int_sptr(int* sptr) {  // No need to pass the length.    size_t length = sptr_size(sptr) / sizeof(int);    if (length) {        printf(%d, sptr[0]);        for (size_t i = 1; i < length; i++) {            printf(, %d, sptr[i]);        }    }    printf(\n);}int main(void) {    int* sptr = malloc_sptr(2 * sizeof(int));    if (sptr == NULL) {        return 1;    }    sptr[0] = 123;    sptr[1] = 231;    print_int_sptr(sptr);  // Expect: 123, 231    // Allocate 1 more int    int* temp = rel_realloc_sptr(sptr, sizeof(int));    if (temp == NULL) {        free_sptr(sptr);        return 1;    }    sptr = temp;    sptr[2] = 321;    print_int_sptr(sptr);  // Expect: 123, 231, 321    free_sptr(sptr);    sptr = calloc_sptr(5, sizeof(int));    if (sptr == NULL) {        return 1;    }    sptr[4] = 5;    print_int_sptr(sptr);  // Expect: 0, 0, 0, 0, 5    free_sptr(sptr);}
A pointer that stores its size at the front
c;memory management