In my opinion, you should learn C first in order to properly understand the base upon
which C++ is built. Pick up a copy of "The C Programming Language" by
Kernighan and Ritchie, widely considered the best reference on the language, and start
reading through it. Once you fully understand C, you'll have the low-level base you
need.
I totally agree. Learning calling conventions and how functions actually work really
helped me understand how the C language works as a whole.
The inventor of the C++ language would disagree with you - his words "If you want
to learn C++, learn C++".
Assembler and C don't have generic programming, polymorphic method dispatch,
exceptions, operator overloading, constructors/destructors etc. So C++ is way more
high-level than C, and those are the good parts of C++. The "old fashioned"
part of C++ (the pointers that have the power to trash anything else in the address
space) is the really bad part; it's perhaps worth understanding if only to get across
the notion of what a poor choice of abstraction it makes for general programming.
I disagree with the sentiment that you need to learn C or assembly language first. C++
and C may be similar in theory but are very different in terms of practical use. One
gains little to nothing in the way of C++ idioms by using only C, and while it is good
to have practical experience in multiple languages, it's an exercise in futility to
specify prerequisites in language learning. I think the best way to learn the concepts
of programming is to sit down with someone who understands them well and just talk
about it, be that on StackOverflow, in forums, or, if you're lucky, in person.
At the end of the day, I think programming really isn't all that hard, and you may
need someone to explain it right just one time to have everything click. It's all
about rehashing the same simple concepts over and over to build complex and beautiful
machines.
I would suggest learning assembly language first. This will give you a very solid
foundation in what is happening at a low level. This will also help to reinforce the
idea that "everything is really just an address".
Taking a class which focuses on assembly language is advisable since it will
"force" you to learn it (personally, I don't think ASM is /that/ fun, but it
was worthwhile [and a requirement for graduation] for me to take the class).
After you know assembly, go on to C and C++.
Have a lot of fun!
If you want to understand the underlying concepts of programming languages, I would
suggest a book such as John Mitchell's Concepts in Programming Languages. Follow this
up by writing a few parsers/interpreters for simple languages. Another good resources
is SICP, which is specific to Scheme (a LISP dialect), and available in full here.
Once you've learned a few languages, it doesn't take too long to pick up the syntax
and semantics of a new one (the core libraries on the other hand, can take quite a
while to be familiarized with).
If you want to learn about how today's computers work, I'd recommend learning C and
reading books such as Tanenbaum's Modern Operating Systems. C is useful in this
context mostly for reading systems level code. Implementing a (very) simple operating
system can be incredibly educational. However, something as simple as implementing a
basic shell (like bourne shell, except simpler) is probably a better place to start.
I'd also recommend learning about how networking works specifically, since it's such
an integral part of modern computer systems.
Personally, I don't think C++ is any great loss in system development. There are still
fields in which it is useful, but these are very specialized. C++ was never a good
general purpose teaching language and while many good engineers started out learning
C++, I don't believe there's any causality here. If you want to learn about pointers
and memory management, it's much better to learn C, which doesn't add a plethora of
other new language features in addition to the pointers and memory management.
Assembly Language.
Start with the Z-80. Then add 'x86. Then try 68000. Then the TI 320 series of DSP. You
might also wish to add the Z-8. Just to see how different machines do it.
Understanding the principles of assembly language is very helpful and not difficult
(registers, 3 address codes, knowing what the instruction sets contain, etc.) will
help. IMHO the effort of being able to write a program in assembly isn't worth it. You
rarely ever need to go more low-level than C.
Set up a performant C++ compiling environment such as Microsoft Visual C++ 2008
Express and go through all links in Bjarne Strousrup's The C++ Programming Language
site, beginning with C++ Style and Technique FAQ. If you are experimented in any other
language you don't need more :-) cheers, AR
C and C++ make some basic underlying programming concepts more evident, but they
weren't designed by God. I'd second the suggestion to study the actual low-level
systems behind your low-level code: operating systems, compilers/runtimes (try
"Essentials of Programming Languages"), and machine architecture.
P.S. In general it may be better to study C++ on its own, rather than starting with C,
but for your particular purpose -- getting more intimate with low-level, unsafe
constructs such as pointers, after already learning Java -- I think it's better to
start with C (and K&R) where these are front and center.
I think you should start with C, but not as a necessary preamble for learning C++.
Rather, for learning C. In other words, while you learn C put your efforts into
learning the language, feeling the philosophy of the language and focusing on letting
it sip into your skin. Be a good C programmer and you will be a good programmer,
period. Not just a good C++ programmer -- this has nothing to do with learning C --
but a good programmer.
There's another reason for learning C first. It's easier than C++, much easier than
C++, and it bridges well to C++ (in contrast to Java, which doesn't in all aspects but
the most superficial object-oriented ones). I'm not talking about the syntax
similarities: I'm talking about low-level programming. I'm talking about the concepts
of pointers, which exist as themselves and in the form of iterators in C++. You can
pass around functions in C, and you can pass around function objects in C++. C is fast
to learn, and it will warm you up very effectively.
Learning C will also eliminate the fear of free functions some pure OO programmers
tend to have. C++ is a hybrid language, and C truly is a subset of C++, not just by
syntax but by philosophy as well.
Start by getting yourself the K&R book and drinking it through. You won't regret
this.