Most malloc implementations don't provide what you want (the starting address of a dynamically allocated block, given some internal pointer to it). And the standards don't require anything like that. So you may want to use both pointer to base, and offset (perhaps packing them inside some C++ class fat_pointer with operator* and operator-> giving the illusion of pointers, etc, etc).
You could of course re-implement your own malloc above operating system memory segment allocation (i.e. mmap(2) on Linux or Posix) and de-allocation munmap(2) primitive syscalls.
You could also have your specialized allocator; it might allocate your zones with a large power-of-two alignment (e.g. 256 or 4096 bytes) using posix_memalign, then use bits manipulation on the intptr_t cast of your pointer.
Notice that implementing any serious memory allocator means caring about unportable details of your operating system and architecture (alignment, ...).
You could also use Boehm's conservative garbage collector, that is use GC_malloc instead of malloc (and don't bother GC_free-ing your dynamic data); then you have the GC_base function which does exactly what you want:
/* Return a pointer to the base (lowest address) of an object given */
/* a pointer to a location within the object. */
/* I.e. map an interior pointer to the corresponding bas pointer. */
/* Note that with debugging allocation, this returns a pointer to the */
/* actual base of the object, i.e. the debug information, not to */
/* the base of the user object. */
/* Return 0 if displaced_pointer doesn't point to within a valid */
/* object. */
/* Note that a deallocated object in the garbage collected heap */
/* may be considered valid, even if it has been deallocated with */
/* GC_free. */
GC_API void * GC_base(void * displaced_pointer);
_msizethat gives the size of the allocation that the pointer itself doesn't have size field in it. Couldn't here beMemStarttoo?_msizeisn't part of standard C and frankly, as a fresh beginner you will just create endless trouble for yourself if you try to use things with names that start with underscore (they're internal implementation details). also, after adding 3 to the pointer you have discarded the information about where the memory block begins. i'm not sure if your expression will even compile, but i gather that the intent is to increase the pointer address by 3.char *c = (new char[12])+3;and internally C++ knows the size of dynamically allocated arrays (to be able todelete[]them).