I want to know, why is it too hard to make a program run in many OSes, like Windows and Linux, without including glue code. They all share the same architecture (x86), so I
Why C primitive types is not portable and the whole language?
The primitive types are portable in that they're guaranteed to support a minimum range of values (e.g., the int type must at least support values in the range -32767 to 32767). They're not guaranteed to have the same size or alignment restrictions because different architectures have different requirements.
The C standard tries to strike a reasonable balance between portability, performance, and ease of implementation, meaning that there are compromises in all three areas. It's possible to write C programs that are useful and trivially portable, but that means limiting yourself to a command-line driven interface, simple file I/O, and making no assumptions about word size or alignment.
Remember that C is a product of the early '70s, when the dominant computing environment consisted of large, time-share systems accessed via dumb character-based terminals; processor time and memory were expensive, and it was rare for a data center to support more than one or two different platforms at a time, so performance was the bigger concern than byte-for-byte portability. Forty years later that's no longer the case, but there's also forty years of legacy code to support, so the language definition can't change too radically.