This is a followup to Can a char array be used with any data type?
I know about dynamic memory and common implementations of malloc, references can be found on wikipedia. I also know that the pointer returned by malloc can be cast to whatever the programmer wants, without even a warning because the standard states in 6.3.2.3 Pointers §1
A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
The question is assuming I have a freestanding environment without malloc
and free
, how can I build in conformant C an implementation of those two functions?
If I take some freedom regarding the standard, it is easy:
- start with a large character array
- use a reasonably large alignment (8 should be enough for many architectures)
- implement an algorithm that returns addresses from that array, at that alignment, keeping track of what has been allocated - nice examples can be found in malloc implementation?
The problem is that the effective type of the pointers returned by that implementation will still be char *
And standard says in same paragraph § 7
A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer.
That does not seem to allow me to pretend that what was declared as simple characters can magically contains another type, and even different types in different part of this array or at different moments in same part. Said differently dereferencing such pointers seem undefined behaviour with a strict interpretation of standard. That is why common idioms use memcpy
instead of aliasing when you get a byte representation of an object in a string buffer, for example when you read it from a network stream.
So how can I build a conformant implementation of malloc in pure C???
(ptr &7) == 0
means that you're 64 bit aligned) This means that you can safely cast the pointer to any 64bit aligned type (fromchar
which is 1 byte aligned up toint64_t
). Notice that 8 byte alignment limits you to 64bit systems (there are 128 bit systems out there). Also notice thatmalloc
assumes ownership of the stack's break (sbrk
) and some standard libraries usemalloc
internally - this means you shouldn't usesbrk
ever. In fact, you should consider it deprecated. – Liles_Alignas ( max_align_t )
. – Taxableptr
is of pointer type, thenptr & 7
is a constraint violation. You can convert a pointer to an integer type (there may or may not be an integer type for which the conversion doesn't lose information), but there's no defined relationship between the low-order bits of the converted integer and the alignment of the pointer.sbrk
is not, and never has been, part of standard C; it's an implementation detail that likely doesn't even exist on many systems. Even POSIX doesn't define it. – Taxableptr & 7
, the order of bits for the7
and theptr
should match on all systems (as the system's bit order is consistent), so that the memory alignment will match. As for casting theptr
to an integer, I believe theuintptr_t
was designed exactly for this purpose. – Lilesuintptr_t
was designed for this purpose, but it's not guaranteed to exist. A system whose largest integer type isn't big enough to hold a converted pointer won't defineuintptr_t
. (I know of no such systems, but they could exist -- and this is a language-lawyer question.) As for the low-order bits, I've actually worked on systems where they don't behave the way you assume (Cray vector systems, where machine pointers point to 64-bit words and byte offsets are stored in the high-order 3 bits). The standard says very little about how pointers are represented. – Taxablechar
andchar*
are kind of special because in the olden dayschar
andint
where often mixed (tons of function taking a char are defined as taking an int) andvoid*
andchar*
where confused as well. Some implementation hadmalloc
returnchar*
. Or NULL being(char*)0
. I'm not sure if any of that is still legal in modern C but there likely is still legacy cruft left over allowing the conversion from a memory blob declared char[] to any type. – Windproof