Most programming languages fall in two categories: interpreted, and compiled languages.
A compiled language is translated by a compiler into machine code, the language the CPU directly executes step by step. An interpreted language, on the other hand, uses an intermediary, an interpreter, to run the language code. The interpreter is itself another program, usually itself compiled to machine code.
PHP is an interpreted language. You need a separate program to run PHP code, the computer does not run the program directly. That separate program, the PHP interpreter, is itself written in C.
C# is a compiled language, but it is not compiled to machine code. Instead, it is compiled to a specialist language, byte code, to be run on a virtual machine. Java is another example of such a setup. You could see it as a hybrid between compilation and interpretation, where the virtual machine is an interpreter. The virtual machine for C# (the CLI, or Common Language Infrastructure) is written in C++.
Other examples are:
- Python: The Python interpreter compiles Python code to Python bytecode, then interprets the bytecode. The interpreter itself is written in C. New implementations have since been added, including one that compiles python to run on the same CLI used for C#, called IronPython, and one that runs on the Java virtual machine, Jython. To complete the circle, there is Python version written in Python, PyPy.
- Ruby: Ruby started out as a pure interpreted language, but the most recent version switched to using bytecode. For Ruby, too, there is a project that compiles to the CLI, named IronRuby, and one for the Java VM, JRuby.