That will only give you a feel for how a particular compiler
translates C constructs into machine code.
The context was "learning C". You don't learn C by only observing what a
particular compiler does - C has lots and lots of implementation-
defined, unspecified and undefined behaviour. If you really learn C[1],
you learn that almost any feature can be implemented differently.
So by examining the output from your C compiler you may find that it
evaluates arguments for functions from right to left, pushing each on
the stack immediately. But the C standard (and every textbook worth its
salt) tells you that the order is unspecified[2], so you start thinking
about other ways a compiler could implement this (e.g., evaluate from
left to right but push in reverse order, evaluate from left to right and
pass an argument count, pass the first n arguments in registers, do
it differently for functions with a fixed number of arguments and
functions with a variable number of arguments, ...) and why it was
implemented in this specific way.
Of course it helps if you actually have access to different compilers
and different architectures. As I said, I already knew a bit of 6502 and
Z80 assembler (and machine code - those were the days of PEEK and
POKE). I first learned programming C on an 8086 and at the university I
had access to a VAX. And I discovered comp.lang.c, where lots of very
knowledgeable people (among them Henry Spencer, Doug Gwyn and Chris
Torek) were quick to disabuse you of any superstitions you may have
aquired by lack of experience.
It won't give you a feel for, e.g., the architecture, translations of
constructs in other languages,
Yes, it does. "A feel" is not the same as knowledge. But if you have
seen what a C compiler does you do have a feel for what a compiler in a
similar imperative language might do.
instructions generated only from assembler code.
True, but mostly irrelevant in this context. Very little code today is
hand-crafted in assembler, so "what is actually executed at machine code
level" (as you wrote in an earlier posting) is usually generated by a
compiler. And you don't have to understand every detail to get "a sense"
or "a feel".
As an introductory language, "Processing"[1] might be a good choice.
Probably kinder than what they did to us, which was to teach us
machine language before introducing the concept of an assembler :-(
Helmut Schauer did that in his excellent "Introduction to CS" course at
the TU Vienna in the mid-1980's. And he introduced microcode before
machine code, adders before microcode, nand and nor gates before adders,
transistors before gates, and semiconductors before transistors. The
bottom-up approach makes sense, as does the historical approach (teach
concepts in the order they were invented). At least for a university
course. If you want to teach a bit of programming to a kid, you probably
should take a different approach.
hp
[1] You can't do that in 21 days. See
http://www.norvig.com/21-days.html
[2] I think its unspecified, not undefined or implementation-defined.
Too lazy to look it up, and it doesn't make a difference here.