C and C++ for Java Programmers


By Alex Allain

So you want to learn C (or C++), and you already know Java--good for you! Once you've learned one programming language, the next one will be easier; you've already gotten past challenges like how to think about programming, how to design basic programs and algorithms and how to debug. With C (or C++), you'll learn about a powerful, high-performance lanugage that provides you with direct access to memory and native libraries without JNI.

Java, C and C++ have a pretty similar syntax for basic concepts. Most of the basic constructs like if statements, loops, function syntax, switch case statements and concepts like recursion are still valid. Many other concepts like the syntax for comments, and the idea of static class variables, also hold in both Java and C++. Many of these differences are covered by the Java vs C++ syntax cheat sheet.

There are some larger differences between the languages though. Once you've gotten your feet wet and found the really basic stuff like main being a free-standing function rather than part of a class, or the fact that you use cout/cin for output/input in C++ or printf/scanf in C, you'll want to start drawing specific comparisons between Java and C++.

Differences between Java and C-like Languages

Toolset and compilation model

In Java, you need a Java VM and a Java compiler, and the Java compiler produces class files that the VM understands. In C and C++, you don't need a VM--the result of a build is an EE file that will run on the native OS. Similar to Java, you can individually compile source files into object files, but the act of creating the EXE file is called linking (it's a little bit like creating a JAR file in Java). You can read more about the basics of compilers and about the compilation and linking process. Of course, the most important thing is to actually get a compiler set up. I recommend using gcc/g++ on Linux, Code::Blocks with MinGW on Windows, or XCode on Mac.

Import vs the C preprocessor

One of the most noticeable differences in compilation is that Java uses imports and does not have a preprocessor--if you're coming from Java, you're used to using import statements to include references to classes from the Java class library. In C and C++, you instead include header files that provide declarations for library objects, and you may also need to use using declarations to provide short names. The equivalent of something like

 
import java.lang.String;
in C++ would be:
 
#include <string>
using namespace std;

You'll find that C and C++ takes much longer to compile than Java because include statements require a great deal of parsing.

Memory Allocation

Java handles memory for you, automatically freeing memory when it is no longer used (garbage collecting it). In C and C++, you must deallocate memory that was allocated:

In C++

 
int *p_int = new int;
// use p_int
delete p_int;

In C:

 
#include <stdlib.h> // needed for malloc and free!
int *p_int = malloc(sizeof(*p_int));
// use p_int
free( p_int );

Moreover, Java provides relatively limited ability to manipulate memory addresses. In C and C++, pointers (C version) are much more powerful (and dangerous). You have to manually free them when you're done (or use a smart pointer), and you will also want to become familiar with more low level manipulation such as pointer arithmetic, which is often used in low level programming.

The fact that you are responsible for freeing memory yourself means that your program designs need to be more careful about who actually owns memory--who is responsible for freeing it. For example, if you have a data structure that stores allocated memory, in Java you don't need to worry about freeing that memory because the garbage collector will do it for you. In C and C++, you have to decide if the data structure is responsible for freeing that memory, or if some other code that uses that data structure has the responsibility to free that memory. It's just one more thing that your design needs to take into account.

Not everything is an object

Not everything is an object in C or C++ (in fact, C doesn't even support classes the way that Java does). If you're used to thinking of designs in terms of objects, you'll need to have a more procedural mindset for programming in C. In C++, you can of course create objects for everything, but you'll find that C++ programs usually use some free-standing functions that do not belong to classes.

Security

Java was designed with an awareness of security, where everything is networked and there are thousands of threats. C was designed before the first internet worm! Java has features like range-checked arrays, immutable strings, auto-resizing containers and garbage collection that prevent many common security problems like buffer overflows and double-free attacks. When you're working with C or C++, you must be careful and security conscious when working even with basic language features. The wires are live, and they aren't insulated.

For example, in Java, if you access an element past the end of an array:

 
int[] values = new int[ 10 ];
values[ 20 ] = 2; // error! You get an ArrayIndexOutOfBoundsException

In C or C++, the same operation results in...well, it just writes the data there.

 
int values[ 10 ];
values[ 20 ] = 2;

This can result in a security problem in some cases--particularly when processing input from outside your program, because it can be used to let attackers write values to memory that you didn't want them to write to. For example, overwriting a Boolean value that controls access to a particular subsystem. You wouldn't write it yourself, but if someone can write past the end of the array, and that Boolean is stored there, the attacker can write it.

Of course, this doesn't usually happen because you wrote a hard-coded index that was out of bounds; the problems usually happen when working with input to your program--perhaps you have a fixed size array that's storing some network packets, or you have a string that you're copying onto a smaller string that can't fit all the data. No matter what language you use, working with input requires care, but in careful, but in C and C++, the consequences of a mistake are often much worse. See this article on writing secure code for more information about how to protect yourself from these attacks.

C for Java Programmers

It's worth mentioning a few things about C specifically: C lacks many of the niceties that you are used to! The standard library is much more limited, C doesn't have the same level of support for Unicode, you don't have classes, interfaces, garbage collection, Java annotations, reflection, or exceptions. You'll need to spend time really understanding pointers and C style strings in order to be productive in the language. C also does not support Java generics. If you want to get the same kinds of generic data structures, you'll need to use typecasting void* pointers.

C++ for Java Programmers

C++ has lots of improvements over C that make it easier to work with, and in some ways similar to Java. C++ has exceptions and classes (and while it doesn't have interfaces, it does have multiple inheritance, which can be used to create interfaces with abstract classes). The syntax for C++ classes is, however, different from the syntax for Java classes, as are some of the basic idioms of use (for example, methods are final by default, and have to be explicitly made virtual), so you'll want to spend some time familiarizing yourself with the differences.

C++ has templates, which are in some ways even better than Java generics (for one thing, they are computed at compile time so they are more efficient). Again, like classes, the syntax for templates does differ from Java generics although both allow basic parameterized types. Templates can also be used for metaprogramming, which can sometimes be used to achieve similar effects.

Stack based objects

One of the more important concepts in C and C++ programming is the use stack based objects that do not require dynamic memory alloation. In Java, except for primitive types like int or char, you must always allocate memory using new. One of the design goals of C++ is to make it so that memory allocation happens only when needed, and so you can declare objects on the stack, passing arguments to the constructor like normal. For example, here is Java code and equivalent C++ code:

 
MyClass c = new MyClass(); // allocates memory and call's the MyClass constructor

In C++:

 
MyClass c; // no memory allocated, still calls the MyClass constructor

The reason that C++ supports two kinds of memory allocation is to reduce dynamic memory allocation to increase performance.

Pointers or references for polymorphism

Like Java, C++ requires that you pass an object by pointer or by reference in order to call virtual functions. However, in Java, objects are always passed by reference so there is no need to have explicit syntax for it. In C++, on the other hand, because you can have stack-based objects, you must have special syntax for working with pointers or references, and you must decide, when passing objects around, whether or not to pass by value or use a pointer or reference to pass around the original object. For example, here is some code in Java and the equivalent code in C++:

 
interface StringConvertable
{
    public String toString ();
}

class ObjectPrinter
{
    public static void displayObject (StringConvertable obj)
    {
        // calls the virtual toString method on the concrete type passed in
        System.out.println( obj.toString() ); 
    }
}

Now in C++:

 
#include <string>
#include <iostream>

using namespace std;

class StringConvertable
{
    public:
    virtual string toString () = 0;
}; // note the need for a semicolon here in C++

// no class is needed, we can have free-standing functions
void displayObject (StringConvertable* obj)
{
    // calls the virtual toString method on the concrete type passed in
    // the arrow operator is used to access methods of a pointed-to class
    cout << obj->toString() << '\n'; 
}

If we'd written void displayObject (StringConvertable obj) in C++, then this would not have worked properly and in fact it wouldn't compile!

Deterministic finalization

All objects in C++ have a destuctor that is guaranteed to be called when the object is released. The object is released either when it is explicitly freed, using the delete keyword or when it goes out of scope, if it was declared on the stack. Unlike Java, where the finalizer may never be called, in C++ the destructor is always called when the object is released.

As a result, destructors are extremely valuable for managing resources besides memory--for example, sockets or file handles--because it means that you can rely on the destuctor to release them for you, rather than having to do it manually. Code that might look like this in Java:

 
void doStuff ()
{
    HandleHolder h = new HandleHolder(); // allocates some handle that needs to be released
    try
    {
        // do stuff that might throw an exception
    }
    finally 
    {
        h.releaseHandle(); // release the handle
    }
}

Can simply be written:

 

void doStuff ()
{
    HandleHolder h; // allocates some handle that needs to be released
    // do stuff that might throw an exception
} // h's destructor is called here, freeing the handle that was allocated

This kind of pattern can even be used to get a kind of poor man's garbage collection using smart pointers like boost shared_ptr that can do reference counting and delete objects that have no more references to them.

The Standard Template Library

Java has a really large, excellent class library, and this is also an area where C++ excels. The standard template library (STL) provides a large number of common containers and utilities, although it is not as extensive as the Java class libraries. Both the STL and the Java class libraries use templates or generics, respectively. For example, in Java you can create a resizable array like this:

 
import java.util.ArrayList;

ArrayList<Integer> a = new ArrayList<Integer>();
a.add( 10 );
a.add( 20 );
whereas in C++, you'd use the vector type:
 
#include <vector>

vector<int> v; // no allocation needed
v.push_back( 10 );
v.push_back( 20 );

The STL also has a map class similar to Java tree maps and a list class similar to Java's linked list class. Both Java and C++ have the concept of an iterator, but there are some differences, as described in the Java vs C++ cheat sheet.

As a Java programmer, you will want to learn about the STL because it will provide you a lot of the same, or similar, libraries that you are used to working with in Java.

Related Articles

Setting up a compiler using Code::Blocks with MinGW

Java vs C++ Syntax Differences Cheat Sheet

Pointers

Templates in C++

Understanding compiling and linking in C++

The C Preprocessor

Secure programming in C and C++