tags:

views:

441

answers:

8

Possible Duplicate:
Should I learn C before learning C++?

As a professional (Java) programmer and heavy Linux user I feel it's my responsibility to learn some C (even though I may never use it professionally), just to make me a better coder.

Two questions :

  1. Should I try C or C++ first - I realise they are different languages with some common ground. Is it useful to learn a bit of both, or just try one? I hear C++ is a bit of a nightmare behemoth of a language.

  2. What are the best resources (books, tutorials, practice programs, reference code) for a Java developer like myself.

Thanks

+16  A: 

C is simple to learn, difficult to master. as a Java programmer the barrier will be memory and structure .. and undoing the damage Java may have done to the algorithm producing portions of your brain ;)

I would recommend getting familiar with the GCC toolchain on your Linux box, through tutorials on the Internet. Then read The C Programming Language, and a copy of Linux Application Development doesn't hurt. Also, on Linux glib will save you from reinventing the wheel ... but at least try to create your own linked-list, hashmap, graph and other API to learn. Pointer arithmetic, arrays and learning that elements such as structs are just named-offsets in a binary chunk are all important. Spend time with malloc and free and memcheck. With C, your tools and toolchain are very important and the IDE isn't necessarily your friend when learning.

I would pick C over C++ as C is a good foundation to get used to the memory management and pointer usage of C.

The best thing you can do is apply what you learn to a real project. But be prepared to bash your head against the wall allot in Valgrind and GDB. I have been programming C for years, and I am still no C monk.

I do agree that C is a great language, it shows up a bad programmer. But remember:

Any sufficiently complicated C program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.

The moral of which is learn other languages too, rather than just C-derived ones! Consider some Lisp dialect, Erlang (which is cool at the moment), Haskell, etc. They will expand your horizons from the 2x2 cell of Java. Consider looking at SICP too.

Aiden Bell
Eh, C isn't particularly difficult to master. C++ is difficult to master, and that's pretty much the reason why C is better suited for some projects.
jalf
I agree, already in the process of learning Clojure ;)
lucas1000001
@jalf - I disagree. C is simple, no doubt, but beauty is in application and elegance. Mastery is in producing beautiful C programs not ones that treat memory and logic like crap.
Aiden Bell
I disagree about C before C++. Especially coming from an OO/Java background. The posts here might help him decide, I suggest C++ and not C. http://stackoverflow.com/questions/145096/is-it-true-that-there-is-no-need-to-learn-c-because-c-contains-everything/145098#145098
KevenK
How is C++ difficult to master compared to C? You can do most of C in C++. You don't have to write all the structures yourself (something you _should_ be doing...).
mathepic
@KevenK C++ before C doesn't make sense at all. C is (+/- some differences) a subset of C++. Even if you are learning "just" C++ you will learn C in the process. The problem is that you will miss the part describing the differences between C and C++ (which is not good).
Let_Me_Be
@mathepic: some of us distinguish between "writing code that is accepted by a C++ compiler" and actually writing good C++ code (which I'd expect someone who "mastered" the language to do
jalf
@Aiden: C being easy to learn is one of the main reasons it is used in the Linux kernel: they need a language that people can pick up and use with a minimum of difficulty, and still write reasonably solid code. My point was simply that as much as I prefer C++, C is definitely *much* easier to master.
jalf
+3  A: 

In response to my comment, and your saying you could not find anything useful:

1) http://stackoverflow.com/questions/598552/should-i-learn-c-before-learning-c

2) http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list http://stackoverflow.com/questions/2963019/how-to-learn-proper-c

Other potentially useful stuff: http://stackoverflow.com/questions/251007/how-difficult-is-it-to-turn-a-java-school-programmer-into-a-c-or-c-programmer

KevenK
Thanks. The Java twist was the key point I was looking for (i.e. I don't want the whole 'this is a loop', 'this is a variable' treatment from a C book)- I think the last one may be more relevant than the others.
lucas1000001
+4  A: 

Regarding (1), I'd probably say C. It's a lot more foreign. Since your goal is to be multilingual for its own sake, moving towards a language that is much different than Java will probably be more useful than learning C++, which will probably make you angry. C++ gets a lot of crap from people, and it's not necessarily awful, but the primary reason is that it is trying to force a new paradigm into the structure of C, which doesn't work as well as a language that starts with that paradigm in the first place.

For (2), I would highly, highly recommend K&R. It assumes some programming familiarity, is brief, to the point, but also is deep enough to explain concepts. It doesn't include exercises, however, which you'll have to find elsewhere. I learned C on the job, I'm afraid (and still paying for it!) so I can't give you educated help there.

Spencer Nelson
+6  A: 
  1. It depends on what you want to learn. I think it's probably best to sit back and consider why you really want to do this at all. If Java does what you want, and you're just doing this out of some misplaced sense of duty, I think there are probably better ways to spend your time. The reputation of C++ as a "nightmare behemoth" is spread mostly by insecure Java programmers trying to justify what, in their hearts, they know to have been a second-rate choice1.
  2. There are a couple of books specifically written for Java programmers learning C and/or C++. Though it's not specifically for Java programmers, if you do decide on C++ rather than C, I'd consider Acclerated C++.

1I'm at least sort of joking, of course, but there are an almost amazing number of Java programmers who seem to have a chip on their shoulder. If you tell somebody who uses Python or Ruby (for just a couple of examples) that it's slow, the typical reaction is them looking a little puzzled and saying something like: "If you say so -- it seems fast enough to me." Suggesting the same about Java is practically guaranteed to produce claims that you're obviously ignorant and expressing nothing but blind hatred.

Edit: As far as choosing between C and C++ goes, for somebody accustomed to Java, C will simply be an exercise in frustration. The difference in language would require considerable adjustment anyway, but moving from a library the size of Java's to one the size of C's will simply result destroying his productivity for quite a while, and is more likely to just prejudice him again all languages with "C" in the name than help him actually learn anything.

Moving directly from Java to C is like taking somebody whose idea of a sporty car is when he drives the Lincoln Town Car instead of being chauffeured in the limousine, and when he decides racing is cool, you dump him directly in the seat of an Outlaw sprint car. Give him a chance in (not only much safer, but actually faster) street-legal sports car first...

Jerry Coffin
If you say so -- Java programmers seem normal enough to me.
GregS
well, if you surround yourself with crazy people, I'm sure they'd seem normal too. ;) I can definitely recognize what Jerry is talking about. Without getting into whether or not Java is *actually* a second-rate language, Java programmers often do seem to have some kind of inferiority complex, like they feel they're not "real" programmers until they've learned C++. Where a Python or Ruby or Haskell programmer just couldn't care less about a primitive language like C++, a Java programmer often seems to have a feeling that they've taken "the easy way out" and that it reflects badly on them.
jalf
@jalf Its the reputation that C/C++ have given Java, as well as its label as an "Introductory language" thats taught at most schools. I'll tell you that I kinda suffer from this, which pushed me to learn C#. The difference with Python is that its dynamic, newish, and very popular.
TheLQ
+8  A: 

If the goal is to make you a better coder, aim for languages that actually try to be different. Java, C++ and C are all closely related.

True, one is primarily a procedural language, one tries really hard to pretend to be OOP, and one is a mix of at least 4 different paradigms, but they're all imperative languages, they all share a lot of syntax, and basically, they're all part of the same family of languages.

Learning C isn't going to teach you anything dramatically new. It might teach you a bit about memory layout and such, but you can learn that in many other ways, and it's just not very relevant to a Java programmer.

On the other hand, the language is relatively easy to pick up, and widely used for a lot of Linux software, so if you want to contribute to any of those, learning C is a good idea. It just won't make you a much better Java programmer.

As for C++, calling it a "nightmare behemoth of a language" probably isn't far from the truth. It is big and complex and full of wierd pitfalls and traps for the unwary beginner.

but it also has some redeeming qualities. For one thing, it is one of the only languages to support the generic programming paradigm, and that allows you to express many advanced concepts very concisely, and with a high degree of flexibility and code reuse.

It's a language that'll probably both make you hate C++ for being such an overengineered mess, and all other languages for missing C++ features that'd have made your code so much simpler.

Again, learning C++ won't make a huge difference to you as a Java programmer, except that it'll reveal a number of shortcomings in Java that you weren't aware of until now.

Learning either language is good, but what's better is learning something different.

Learn SML or Scheme or Haskell. Or Ruby, Python or Smalltalk. How about Erlang or Occam? Or Prolog.

Learn something that isn't either Java's sibling or ancestor, something that is designed from scratch to have nothing in common with Java. Learn a functional language like SML, or a dynamically typed one like Python, or one that radically changes how you deal with concurrency, like Erlang.

jalf
+1: This says everything I wanted to say, but didn't want to fit into a comment.
Dennis Zickefoose
+9  A: 

Coming from ASM, C, then C++, and finally landing (forced) into the Java territory, I thought I may provide an opinion about the subject.

First, with all due respect to the Java community, the business experience shows that while C/C++ programmers can get used to the Java principles and programming (it may not be that easy), the opposite happens more rarely. In other terms, a C++ programmer will have to learn and cope with tons of Java rules (Frameworks...) but she will eventually (and usually) be able to produce a long term working code by injecting a lot of her system experience into the process. A Java programmer going to C, used to more theoretical principles, and strict structure rules may

  • feel insecure as she has to decide many things, like program organization and structure
  • feel surprised with the pointers, and memory management: allocation and freeing, which has to be thought carefully - discovering the world of memory leaks
  • feel discouraged, as the bugs won't appear black on white in a console dictated by the JVM through 200 lines of stack trace, but may happen at a deeper / system level, maybe caught thanks to an IDE in front of which the Java programmer will contemplate some assembly code for the 1st time in her life
  • feel perplex as to what algorithm and how to implement it, the one that was integrated into Java that she never had to worry about...

So, now, my task is to help you to feel secure, confident, and motivated before learning C/C++!

My advice is to start with C, because

  • C by itself owns all the very concepts you never had to face with Java
  • as a Java programmer you already have a classes 'approach', and starting with C++, you may be tempted to stick to the Java OO principles
  • C principles are limited to a few. C looks like the very last human thing before entering the dark world of assembly language.

What I would emphasize during the C study is, for instance

  • Pointers Java uses pointers of course, but hides its access while actually passing classes to methods as pointers. In C, you will have to learn the difference between by value and by reference. Also, the more subtle difference between char x[3] and char *x = "ab". And how convenient pointers are to go through an array etc..., you know *++x or *x++. A lot has been said about pointers, my advice would be

    1. always keep control, i.e. don't put too many indirections when not necessary
    2. don't typedef pointers, like typedef int *pointerToInt ; it seems easier at first (pointerToInt pi instead of int *pi) after a few levels, I prefer to count the stars than the 'pointerTo' [some big cies do that]. Except maybe the pointers to functions, unreadable anyway.
  • Memory When you need memory, you allocate it, and when you don't need it anymore, you free it. Easy. The thing is to allocate the right amount, and not to free it twice... Have to get used to that. And get used to the heap, the stack... And When your program runs and address NULL (0) you may have a visible exception. Maybe not.

  • Data structure So you want to use a convenient HashMap? Sure, after you developed it. Or there are some libraries you can link that do that kind of thing, just chose the right one. To be fair, when programming in C, you [have to] think different, and may find a more appropriate algorithm than a map for a given problem.

All in all, you will feel disoriented at first, but eventually (unless you have nightmares) you will find before you a lot of room for fun and pleasure. C allows a person to program with complete freedom: C goes according to your ideas, not the opposite.

ring0
lol, your right that errors tend to be buried in massive stack traces/tread dumps. But I think that most memory problems can simply be solved by spending some time in the profiler. This is an essential learning experience for Java people to prevent memory leaks.
TheLQ
Thankyou for your very detailed explanation - very much appreciated!
lucas1000001
+1, some good advice here.
Aiden Bell
+3  A: 

Since you're doing this for self-fulfillment and learning, I say go for broke and give C++ a try.

A small preface before I elaborate: I used to work primarily with C++ and have never worked with C code of any significant size. Now I work with C# for the most part, only using C++ on rare occasions.

I think C++ is a better option because:

  • It's a partial super-set of C: C programs will generally not compile as C++ programs, but the overlap between the two languages is substantial enough that it shouldn't be difficult for you to re-target your skills to work with C code if you need to.
  • C++ will introduce you to more concepts: You'll get all the fun of memory management and bit twiddling that you can do in C. But you'll also get to see generics like you've never seen them before, how algorithms can be written independently from containers, how to do compile-time polymorphism, how multiple inheritance can be actually useful sometimes, etc.
  • You'll learn to appreciate the design of the Java language a lot more: C++ is a complicated languages with many gotchas and edge cases (see the FAQ and the FQA for some examples). By experiencing them for yourself, you'll be able to better understand many of the design decisions that went into making both Java and C#.

It boils down to this: The more you learn the more that you'll be able to learn. And C++ forces a lot of learning on you, definitely more than C. And that's a good thing.

ShaderOp
+1  A: 

C++ will probably feel more familiar to you than C, and will probably be easier to get productive with off the bat. However, C is a much smaller language and should be reasonably straightforward to learn (although beware; by learning C you risk permanent brain damage). My personal reference is "C: A Reference Manual" by Harbison & Steele (currently 5th edition). For C++, I just use the O'Reilly nutshell book.

As a C programmer with some C++ experience and currently making the transition to Java, I can tell you the things about C that are probably going to trip you up almost immediately:

  • C has very little in the way of abstractions; pointers and byte streams are pretty much it. There are no standard container types (lists, maps, etc.). You want anything more sophisticated than a fixed-length array, you will have to roll your own (or use a library developed by someone else).
  • There is no such thing as garbage collection in C. Every byte you allocate dynamically (via malloc() or calloc()) you are on the hook for deallocating (via free()).
  • Arrays in C do not behave like arrays in Java; there are some funky rules regarding array types that at first blush do not make sense (and won't until sufficient brain damage has set in). There is no bounds checking on arrays, and some standard library functions (notably gets() and scanf()) make buffer overrun exploits a real risk.
  • C declaration syntax can get pretty twisted. While you probably won't see anything quite so ugly, declarations like int *(*(*(*f)())[10])(); are possible (f is a pointer to a function returning a pointer to a 10-element array of pointers to functions returning pointer to int`.
  • C implementation limits can vary from platform to platform; for example, the language standard only mandates minimum ranges for types like short, int, and long, but they may be wider than the minimum requirements. If you're expecting an int to always be the same size regardless of platform, you're in for some surprises.
  • Text processing in C is a pain in the ass. Seriously. C does not have a string type as such.
John Bode
There are garbage collectors for C, as third-party libraries.
Donal Fellows