tags:

views:

657

answers:

12

I've been writing Java professionally for the last 5 years. Recently, I've had to dig into JNI a bit to call some Windows specific functions.

This experience has highlighted my poor command of the C (or C++ for that matter) language. My only introduction to C was a brief "dummies" book that I read in high school 11 years ago.

I know that both languages have advanced in that time frame, especially C++ and the standard library.

Would it be appropriate for me to learn C or C++? Which books would be best?

Do folks also have any recommendations for Windows programming as well? I can read through MSDN well enough to figure out certain API calls but I have a feeling I'm missing things in regards to the "big picture".

Thanks

+2  A: 

I think that C++ would be much easier for you to become proficient in than C.

If you've been using Java, you'd have a hard time doing away with conveniences like classes, exceptions, a form of references, dynamic binding, etc. and of course, decent libraries.

However, you should learn C first to make sure you really understand what's under the hood and get to experience pointers and their use and the feeling of working "with no protective gear".

Once you master that, learn about the inheritance mechanisms in C++ and how it's different from Java (e.g., multiple inheritance).

Uri
@Uri, Hey I'm sure Joel would disagree with you about learning C first. Not! (-:
Rob Wells
Actually, I disagree with C++ being easier. Yes, there are classes, but if you use them like Java, you've screwed up. C++ is radically different from Java, and I think it might be easier to just learn the basics in C. Especially if the goal is simply to interface with Win32, C should suffice.
jalf
The OP's description sounded like he was ready to do more full-time C/C++ rather than just JNI. If you're used to classes, mimicking them in C is pointless. C is a great language, but it has its limits.
Uri
Perhaps. As you say, it depends on what he wants to do. For interfacing With Win32, C++ is overkill. But for dedicated native development, I'd prefer C++ as well.
jalf
I disagree with learning C first, rather learn C++ and searcht for the differences between C++ and C later. Unless you are going low-level or to an unsupported platform there will be no use to learn C first. Also, you will avoid learning things in the C way (the bad way).
TomWij
Learning C is much easier than C++, you don't have inheritance, templates, references, everything is whot you see, but I can't argue with you because your only argument is that C is the bad way (which is subjective and is a personal opinion).
Ismael
Function pointers instead of Functors, return codes instead of exceptions, ... Those things are considered bad. Besides that, learning something that's easy to do with C++ can be hard in C. I wouldn't learn a potentially not useful language just because it contains less high-level features.
TomWij
I agree with you that return codes, functions pointers, etc. are old stuff, and is much preferable to user more modern constructions for new code. But if you are writting code at low level (like win32 api) you are stuck with it anyway.
Ismael
But I'm not suggesting that you should not learn C++, my suggestion is to start with C, and then move to C++, which is much better suited for moderns projects, and give you something really powerfull like templates (boost, stl, etc).
Ismael
Java *has* inheritance, templates and references, so those concepts should be clear to him. Learning C++ should not be that much of a stretch.
CShipley
C++'s templates are much trickier, they come with a lot of rules about resolution, specialization, and you can implement compile time inheritance.
Ismael
CShipley: Java does not have templates, and its references are not the same as C++ references. Just because the same *words* exist in both language does not make them identical.
jalf
+1  A: 

This really depends on your strengths and weaknesses. If you really like design patterns, then I'd suggest using C++, but if you just have to implement a couple simple methods in JNI, then I would recommend C. Learning C before C++ should give you a better understanding of memory management without having to worry about some of the complexities of C++ (constructor call order, destructors, and other differences between c++ and java).

I would suggest "The C Programming Language" by Richie and Kernighan as the definitive manual for learning C. http://www.amazon.com/Programming-Language-Dennis-M-Richie/dp/0876925964

If you're on a *nix system, there's ample documentation in the manpages for different functions. For example,

bash$ man malloc

Read my comment on Uri.
TomWij
Design patterns in C - it's the biggest PITA to work with, but it's the best exercise of any.
Tom
+2  A: 

If you have a good understanding of Java, I'd recommend that start with C, if you start directly with C++ there're a lot of differences between it and Java, and you probably will dislike it.

If you are serious about learning both languages I'd recommend "The C++ Programming Language" by Bjarne Stroustrup, and "The C Programming Language" by Dennis Ritchie.

Ismael
Read my comment on Uri.
TomWij
+9  A: 

I guess it depends on your objectives.

If you want to get closer to the machine, then C.

If you want to supplement you knowledge of a OO Java-like layer above C, then C++.

Accelerated C++ (sanitised Amazon link) is an awesome book to learn C++ from the point of view of C++ and not just C with other bits tacked on,

And K'n'R C (sanitised Amazon link) is still the way to go for learning C IMHO!

BTW For C++ follow up with the wisdom of Scott Meyers in the Effective C++ books! And his Effective STL book as well.

HTH

cheers,

Rob

Rob Wells
Great Scott Meyers recommendation. I think his books are terrific. I've never seen the Effective STL book. I had moved onto Java by the time it came out.
duffymo
+24  A: 

Good question. On the surface, it'd be obvious to recommend C++, because "it's object oriented like Java". Only problem is, it's not really true.. C++ allows OOP, yes, but it's just one of several paradigms that C++ supports. Treating C++ like a OOP language (and especially, treating it like Java) will only lead to frustration.

The problem is that Java and C++ don't actually have much in common. Java programmers often believe that Java was inspired by C++, but that's only true if by C++ you mean the very earliest versions of C++, which might more appropriately be called "C with classes". Since then, C++ has transformed completely into its own language with its own way of doing things. It has probably changed far more since then than Java has. A Java programmer back then would still be able to make sense of today's Java code. Not so for C++. So I'd argue that C is actually closer to Java than "modern C++" is. C is what you get if you take Java and strip away the GC and the concept of classes and a few other abstractions. To arrive at C++, you have to add a similar number of features to our hypothetical stripped-down Java as well.

Further, C++ is a remarkably complicated language, and learning it well takes ages. And if you don't learn it well, you're going to shoot yourself in the foot over and over again.

Finally, it depends on your objectives. C++ is a much more modern language than C, and once you learn it, very expressive and powerful and, surprisingly, it can even be very elegant and concise. But the learning curve is nasty. So for native programming in the long term, I'd recommend C++ over C.

But if your goal is primarily to interface with the Win32 API (or other native API's for that matter), you won't need C++. Win32 and most other API's are written in C, not C++, and you most likely won't need very complex code to interface between that and Java in any case.

About learning Win32, you're right, all the details you need are on MSDN. If you want the big picture, Petzold is the book on the subject.

jalf
+1 what a good answer.
Trap
Wow, extremely concise answer. +1
Azreal
A: 

Learn C++.

You will find it very similar to Java with the exception of garbage collection. Additionally, C++ is generally a super set of C, so to some extent by learning C++ you will also be learning C. The converse is not true.

CShipley
Wrong, so wrong. C++ is in no way similar to Java. Java programmers might think so, but I doubt many C++ programmers would agree. And while syntactically, C++ might be *mostly* a superset of C, that doesn't extend to common idioms and paradigms. Programming C++ is nothing like programming C. Or Java
jalf
+1 Jalf's comment.
sixlettervariables
+2 for Jalf's comment
Nemanja Trifunovic
+2 or Jalf. C++ is very different from Java, and it shows whenever I interview a candidate with mostly Java experience (^:
Tom
Write down a list of all the computer languages out there and rate them according to how close they are to Java *linguistically*, C++ will be much closer than many others. C "idioms and paradigms", big words - little meaning. If you learn C++, you can read C much more easily than the converse.
CShipley
@CShipley - If you don't think "intended language usage" (those idioms and paradigms you're downplaying) is as important as the raw syntax, you're not getting the most out of the programming languages you're using.
Tom
+5  A: 

Learn enough C++ to use it as "a better C". You don't have to try to map all of it onto your understanding of Java. All you want is to be able to use C++ objects as abstract data types, new and delete, etc. If STL comes along for the ride, so much the better.

The real question is: Why do you think that JNI is such an absolute necessity? The Windows calls will ruin any thought of keeping your app portable. I'm sitting next to a guy who's having to dig into a Java app that uses JNI. It randomly brings down a server with a SEG FAULT. His hypothesis is that the heap fills up, a JNI call is made to a routine that calls malloc to allocate space on the heap. It's not available, the routine doesn't check the returned pointer for null, deallocates it, and down comes the server. He's still trying to reproduce the error locally, because it requires precise timing to call the JJNI method just before the GC starts up.

100% sure they're required? Just asking....

duffymo
Agree a lot. You really want to avoid C's worst parts, like writing int foo(); instead of int foo(void);.
MSalters
A: 

If your intent is to continue writing JNI code then I'd definitely recommend C++.

In particular, the JNI interface requires you to acquire (and subsequently release) references to Java objects. Using C++ auto variables you can get these references using 'RAII' (Resource Allocation is Initialisation) techniques which makes memory management far simpler.

Alnitak
The JNI interface itself is C-based. While C++ RAII makes the JVM/environment resources easier to manage, it certainly does obfuscate the issue (since Java objects are very different from C++ objects).
Tom
I made no comment about Java vs C objects. But I know that some simple C++ wrappers can dramatically simplify JNI code because I've done it. How about a JNIString that's auto-released on exit, and can automatically cast to a (char *)?
Alnitak
A: 

100% sure they're required? Just asking....

Unfortunately, yes.

Thanks everyone for your answers.

To answer some of the follow up questions, I'm not looking for a career change to C or C++. I'd just like to learn the fundamentals so I don't feel like I'm flying blind when I do need to write bits and pieces.

Kevin
If you're looking to supplant your Java experience, definitely pick up C. I love C++, but I think it's mostly an "experts only" language. C will be much more productive for you to know as a secondary (N-ary?) language, due to its simplicity.
Tom
A: 

In particular, the JNI interface requires you to acquire (and subsequently release) references to Java objects. Using C++ auto variables you can get these references using 'RAII' (Resource Allocation is Initialisation) techniques which makes memory management far simpler.

Thanks, that is helpful. One of the areas that stoked the growing concern in my stomach was dealing with manually managing the memory associated with the JNI objects

Kevin
I don't know JNI, but probably it's a good idea to have a look at boost::shared_ptr<> (see http://boost.org/). This gives you reference counted pointers that automatically release the objects if they are no longer referenced anywhere.
sth
@Kevin - you're already forced to manage resources in Java - everything except memory. That means open files, shared memory segments, network connects, etc. If you focus on generalized resource management instead of just memory management, you'll have a big step up on many Java developers.
Tom
+1  A: 

If you want an excellent resource for C, "The C Programming Language" by Dennis Ritchie is the book to get.

Chris Stewart
duffymo
A: 

If your "main goal" here is to do windows programming, I'd recommend C# over C or C++. However I believe every programmer on Earth, and in Lower orbit, SHOULD know C. Not knowing C++ is acceptable, although you might not get invited to a few parties :) But C is something of a rite of passage, between Applications (high-level) programmer and Library (low-level) programmer.

Robert Gould
Does C# integrate with Java directly? I would expect them both to integrate through a C DLL or similar.
Tom
No by no means does C# integrate with Java, however its easier to move between them as a programmer, and there are even some cross compilers for simple stuff.
Robert Gould