Coming from an operating system background, I find the article's use of "virtual machine" very bizarre. The article confuses very different things by stating that "'runtime', 'virtual machine' and 'abstract machine' are different words for the same fundamental thing".
"global" and "static" are pretty overloaded terms. In LLVM, for example, Global Value Numbering has nothing to do with global values. "const[ant]" is also pretty bad, but that's more because there's several slightly different notions where the distinctions between them are pretty important.
"Virtual machine" has a broader sense than emulation or virtualization within a hypervisor. From the perspective of an assembly programmer, C implements a low level virtual machine that abstracts much of the drudgery that assembly requires. For instance, you can store 32 signed bits in a variable without caring about the native word size and bit representation in the underlying hardware (though in some circumstances you may still care). That is the "virtual" part of C's abstraction.
A java virtual machine runs java byte code. It makes sense because the compiler emits code for a machine that is an abstract concept, not something that physically exists, and the virtual machine executes this bytecode.
In typical use of a C compiler, you get code for the target processor, i.e. x86. In theory, you don't have to worry about the underlying hardware, so you could say you are programming for some abstract machine that runs C code, but it is much less meaningful than saying java has a virtual machine.