Yes, this is safe. The standard library is allowed to define function-like macros for any of its functions, but they must also be available as functions.
C17 7.1.4 (1)
Any
function declared in a header may be additionally implemented as a function-like macro defined
in the header, so if a library function is declared explicitly when its header is included, one of the
techniques shown below can be used to ensure the declaration is not affected by such a macro. Any
macro definition of a function can be suppressed locally by enclosing the name of the function in
parentheses, because the name is then not followed by the left parenthesis that indicates expansion of
a macro function name. For the same syntactic reason, it is permitted to take the address of a library
function even if it is also defined as a macro. [189]
[189] This means that an implementation shall provide an actual function for each library function, even if it also provides a
macro for that function.
So in short, the library's header is allowed to have something like
void *malloc(size_t);
#define malloc(s) __fancy_internal_malloc((s) + 47 | 0x14 * 3)
and so then you can do any of
void *p = malloc(10); // invokes the macro if there is one
void *q = (malloc)(10); // definitely calls the function, not the macro
void *(*allocator)(size_t) = &malloc; // takes address of the function
#undef malloc
void *r = malloc(10); // definitely the function
Of course, the function and the macro must both provide whatever behavior the standard promises (though as Eric Postpischil comments, they do not have to behave identically so long as each is conformant). In particular, it must be safe to allocate with the macro and free with the function, or vice versa. Also, such a macro must evaluate each of its arguments exactly once, so p = malloc(s++); is safe for either the function or the macro.