#pragma
is, by definition, not portable.
And weak linking is done at link time (surprisingly enough). It allows a function (or any symbol, really) with the same signature to override another. That means a strong one will be chosen in preference to the weak one but, if there's no strong one, the weak one will be used.
Include guards are done by the compiler, not the linker, and they do not allow the fallback to a weak one if the strong one's not there. You can simulate the same behavior if you control the source for both functions (by ifdef
-ing for one, ifndef
-ing for the other) but that's not always the case and this is more choosing between two strong functions.
Weak linking allows you to do things like drop in your own malloc()/free()
for debugging purposes while still linking with the library that provides them.