If a compiler correctly determines that code will inevitably fetch a
pointer to an object which has been passed to "free" or "realloc", even if
code will not make any use of the object identified thereby, the Standard will
impose no requirements on what the compiler may or may not do after that point.
Thus, using a construct like:
char *thing = malloc(1000);
int new_size = getData(thing, ...whatever); // Returns needed size
char *new_thing = realloc(thing, new_size);
if (!new_thing)
critical_error("Shrinking allocation failed!");
if (new_thing != thing)
adjust_pointers(thing, new_thing);
thing = new_thing;
might on most implementations allow code to save the effort of recalculating
some pointers in the event that using realloc to shrink an allocated block
doesn't cause the block to move, but there would be nothing illegitimate about
an implementation that unconditionally reported that the shrinking allocation
failed since if it didn't fail code would inevitably attempt a comparison
involving a pointer to a realloc'ed block. For that matter, it would also
be just as legitimate (though less "efficient") for an implementation to
keep the check whether realloc returned null, but allow arbitrary code to
execute if it doesn't.
Personally, I see very little to be gained by preventing programmers from determining testing when certain steps can be skipped. Skipping unnecessary code if a pointer doesn't change may yield significant efficiency improvements in cases where realloc is used to shrink a memory block (such an action is allowed to move the block but on most implementations it usually won't), but it is currently fashionable for compilers to apply their own aggressive optimizations which will break code that tries to use such techniques.