C was designed to actively deal with memory at different levels. There are cases where the difference between short, int, and long, and between float and double, mattered because of memory constraints, architecture, etc. Though it matters less now, there are still environments where it does (e.g, embedded, and in cases where the data is massive), and the transition from mainly 32-bit architectures to 64 bit makes it somewhat of an issue again. (In ten or twenty years when we transition to 128 bit architectures and C/C++ is still popular, it'll again be an issue). You're right though that binary compatibility suffers, which is why you don't want to use these variable type sizes where that matters.
You asked how you would know which to use if you don't know the size, but you do know the size on a given architecture/compiler combination, and if you need to optimize memory at that level, you'd better know it. You can't optimize it that simply across platforms because you can't know their sizes, so you wouldn't want to use those features for that purpose. But a lot of things written in C are platform-specific, which, despite the fashion for "cross platform", does allow for some advantageous optimizations.
<stdint.h>
sizeof(short) == 2 * sizeof(char)
or similar?sizeof(char) == sizeof(short)
, and it makes sense. Unfortunately, there is no way to specify integral number types that way that they'll fit all the possible and existing platforms.